Problem
The repo has no .gitattributes, so binary map assets are subject to git's text/eol handling. On a default Windows clone (core.autocrlf=true — the Git for Windows recommended installer setting), checkout LF→CRLF conversion rewrites map bins: every 0x0A byte in the terrain data grows a 0x0D prefix. The file on disk no longer matches width*height, and the game crashes the moment such a map loads:
Error: Invalid data: buffer size 4855502 incorrect for 2904x1672 terrain plus 4 bytes for dimensions.
at genTerrainFromBin (src/core/game/TerrainMapLoader.ts)
Currently corrupted on a default Windows checkout (7 files): europe/map.bin (+14 bytes), greatlakes/map.bin (+8), korea/map.bin (+2), levant/map.bin (+57), didierfrance/map16x.bin (+113), losangeles/map4x.bin (+1), venice/map4x.bin (+15).
Why it's sneaky
- The committed blobs are clean — verified via
git cat-file -s (e.g. europe/map.bin blob is exactly 4,855,488 = 2904×1672). Corruption happens purely at checkout, so prod/CI (non-Windows or autocrlf off) never sees it. It strictly bites Windows contributors, who get a broken game out of a fresh clone.
- Every map bin is exposed, not just these 7. git's binary-detection heuristic looks for a NUL byte in the first ~8k; terrain data contains none there, so ALL
map*.bin files are classified as "text" and eligible for conversion. The 7 above are simply the maps whose bytes happen to include 0x0A today — any map regenerated in the future can silently join them.
Repro
- Windows, Git for Windows with the default "Checkout Windows-style" setting (
core.autocrlf=true).
- Fresh clone (or fresh worktree checkout).
resources/maps/europe/map.bin is 4,855,502 bytes on disk vs a 4,855,488-byte blob. Verified each inserted byte is a 0x0D immediately preceding an existing 0x0A (14 LFs in the file, 14 CRLF pairs after checkout, +14 bytes exactly).
- Load Europe (or Great Lakes / Korea / Levant) →
genTerrainFromBin throws the size error above.
Fix
One .gitattributes at the repo root immunizes everything forever:
*.bin binary
*.webp binary
*.png binary
(Existing corrupted working copies self-heal on the next checkout of those paths after the attributes land.)
Made and verified by Claude — blob sizes checked against two independent clones, corruption reproduced on demand via a fresh checkout of a pre-.gitattributes revision, and the LF→CRLF byte accounting confirmed exactly (every excess byte is a CR inserted before an existing LF).
Problem
The repo has no
.gitattributes, so binary map assets are subject to git's text/eol handling. On a default Windows clone (core.autocrlf=true— the Git for Windows recommended installer setting), checkout LF→CRLF conversion rewrites map bins: every0x0Abyte in the terrain data grows a0x0Dprefix. The file on disk no longer matcheswidth*height, and the game crashes the moment such a map loads:Currently corrupted on a default Windows checkout (7 files):
europe/map.bin(+14 bytes),greatlakes/map.bin(+8),korea/map.bin(+2),levant/map.bin(+57),didierfrance/map16x.bin(+113),losangeles/map4x.bin(+1),venice/map4x.bin(+15).Why it's sneaky
git cat-file -s(e.g.europe/map.binblob is exactly 4,855,488 = 2904×1672). Corruption happens purely at checkout, so prod/CI (non-Windows or autocrlf off) never sees it. It strictly bites Windows contributors, who get a broken game out of a fresh clone.map*.binfiles are classified as "text" and eligible for conversion. The 7 above are simply the maps whose bytes happen to include0x0Atoday — any map regenerated in the future can silently join them.Repro
core.autocrlf=true).resources/maps/europe/map.binis 4,855,502 bytes on disk vs a 4,855,488-byte blob. Verified each inserted byte is a0x0Dimmediately preceding an existing0x0A(14 LFs in the file, 14 CRLF pairs after checkout, +14 bytes exactly).genTerrainFromBinthrows the size error above.Fix
One
.gitattributesat the repo root immunizes everything forever:(Existing corrupted working copies self-heal on the next checkout of those paths after the attributes land.)
Made and verified by Claude — blob sizes checked against two independent clones, corruption reproduced on demand via a fresh checkout of a pre-
.gitattributesrevision, and the LF→CRLF byte accounting confirmed exactly (every excess byte is a CR inserted before an existing LF).