Fix crash when loading saved tutorial worlds (#1001)

writeRuleFile() was missing the schematic file count integer before the schematic entries. The reader in readRuleFile() expected this count, causing a stream misalignment that led to an assertion failure (Unrecognised schematic version) when reloading a saved tutorial world.

The fix writes the count on save and adds backward-compatible reading that detects old saves (without count) via a peek heuristic and falls back to count-less parsing.

Co-authored-by: MCbabel <MCbabel@users.noreply.github.com>
This commit is contained in:
Marlian
2026-03-10 04:02:39 +01:00
committed by GitHub
parent 58c236ead5
commit 3bcf588fbe

View File

@@ -344,6 +344,7 @@ void GameRuleManager::writeRuleFile(DataOutputStream *dos)
// Write schematic files.
unordered_map<wstring, ConsoleSchematicFile *> *files;
files = getLevelGenerationOptions()->getUnfinishedSchematicFiles();
dos->writeInt((int)files->size());
for ( auto& it : *files )
{
const wstring& filename = it.first;
@@ -497,17 +498,36 @@ bool GameRuleManager::readRuleFile(LevelGenerationOptions *lgo, byte *dIn, UINT
}*/
// subfile
// Old saves didn't write a numFiles count before the schematic entries.
// Detect this: a real count is small, but a UTF filename prefix reads as a large int.
UINT numFiles = contentDis->readInt();
for (UINT i = 0; i < numFiles; i++)
if (lgo->isFromSave() && numFiles > 100)
{
wstring sFilename = contentDis->readUTF();
int length = contentDis->readInt();
byteArray ba( length );
contentDis->read(ba);
levelGenerator->loadSchematicFile(sFilename, ba.data, ba.length);
contentDis->skip(-4);
while (true)
{
int peek = contentDis->readInt();
if (peek <= 100) { contentDis->skip(-4); break; }
contentDis->skip(-4);
wstring sFilename = contentDis->readUTF();
int length = contentDis->readInt();
byteArray ba( length );
contentDis->read(ba);
levelGenerator->loadSchematicFile(sFilename, ba.data, ba.length);
}
}
else
{
for (UINT i = 0; i < numFiles; i++)
{
wstring sFilename = contentDis->readUTF();
int length = contentDis->readInt();
byteArray ba( length );
contentDis->read(ba);
levelGenerator->loadSchematicFile(sFilename, ba.data, ba.length);
}
}
LEVEL_GEN_ID lgoID = LEVEL_GEN_ID_NULL;