From fb7b8739c802b1214659136be20239733be0786b Mon Sep 17 00:00:00 2001 From: terbin Date: Tue, 2 Dec 2025 22:43:51 +0100 Subject: [PATCH 1/2] Fix chunk loading for region files with unpadded sectors Check actual chunk data length instead of full sector allocation when validating chunk boundaries. Some exporters like WorldTools don't pad sectors to 4096-byte boundaries, causing valid chunks at the end of region files to be rejected. --- chunkloader.cpp | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/chunkloader.cpp b/chunkloader.cpp index 8af1ed32..fb0f95f7 100644 --- a/chunkloader.cpp +++ b/chunkloader.cpp @@ -77,12 +77,35 @@ bool ChunkLoader::loadNbtHelper(QString filename, int cx, int cz, QSharedPointer const int chunkStart = coffset * 4096; const int chunkSize = numSectors * 4096; - if (f.size() < (chunkStart + chunkSize)) { - // Chunk not yet fully written by Minecraft + // Check if chunk header (5 bytes: 4 length + 1 compression) is readable + if (f.size() < chunkStart + 5) { + f.close(); + return false; + } + + // Read chunk header to get actual data length + f.seek(chunkStart); + char headerBuf[5]; + if (f.read(headerBuf, 5) != 5) { + f.close(); + return false; + } + const uchar *hdr = reinterpret_cast(headerBuf); + int actualLength = (hdr[0] << 24) | (hdr[1] << 16) | (hdr[2] << 8) | hdr[3]; + + // Sanity check: length must be positive and fit within allocated sectors + if (actualLength <= 0 || actualLength + 4 > chunkSize) { + f.close(); + return false; + } + + // Check actual data fits in file (handles unpadded files like WorldTools exports) + if (f.size() < chunkStart + 4 + actualLength) { + f.close(); return false; } - uchar *raw = f.map(chunkStart, chunkSize); + uchar *raw = f.map(chunkStart, actualLength + 4); if (raw == NULL) { f.close(); return false; From 00fc292d4a57c4d4d5eac2b07a58a3ae3e48525f Mon Sep 17 00:00:00 2001 From: terbin Date: Tue, 2 Dec 2025 23:37:16 +0100 Subject: [PATCH 2/2] Skip map_*.dat files when loading structures to improve world load time Worlds with thousands of in-game maps (map_.dat) were slow to load because loadStructures() parsed every .dat file in data/, even though map files never contain structure data. --- minutor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/minutor.cpp b/minutor.cpp index c77eaca1..e6c206e5 100644 --- a/minutor.cpp +++ b/minutor.cpp @@ -1194,6 +1194,8 @@ void Minutor::loadStructures(QDir path) { // attempt to parse all of the files in the data directory, looking for // generated structures for (auto &fileName : path.entryList(QStringList() << "*.dat")) { + if (fileName.startsWith("map_")) // map files don't contain structures + continue; NBT file(path.filePath(fileName)); auto data = file.at("data");