aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/Common
diff options
context:
space:
mode:
authorMarlian <84173858+MCbabel@users.noreply.github.com>2026-03-10 04:02:39 +0100
committerGitHub <noreply@github.com>2026-03-09 22:02:39 -0500
commit3bcf588fbe041bd9d81f51348c3e98876dc9d4e2 (patch)
treeaf3dfc0f2e28ed9f2e7cb752eb410ec55a4d4df0 /Minecraft.Client/Common
parent58c236ead5c35248a9c993c7b296e41c2799d305 (diff)
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>
Diffstat (limited to 'Minecraft.Client/Common')
-rw-r--r--Minecraft.Client/Common/GameRules/GameRuleManager.cpp38
1 files changed, 29 insertions, 9 deletions
diff --git a/Minecraft.Client/Common/GameRules/GameRuleManager.cpp b/Minecraft.Client/Common/GameRules/GameRuleManager.cpp
index ff294a65..95434c08 100644
--- a/Minecraft.Client/Common/GameRules/GameRuleManager.cpp
+++ b/Minecraft.Client/Common/GameRules/GameRuleManager.cpp
@@ -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++)
- {
- wstring sFilename = contentDis->readUTF();
- int length = contentDis->readInt();
- byteArray ba( length );
-
- contentDis->read(ba);
-
- levelGenerator->loadSchematicFile(sFilename, ba.data, ba.length);
+ if (lgo->isFromSave() && numFiles > 100)
+ {
+ 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;