Folge-Issue zu #128, dort unter „Nicht enthalten“ aufgeführt.
Befund
Pro Layer werden die Zellen als Map "x,y" → Tile-Id gespeichert (src/core/model/tilemap.ts:6). Jede bemalte Zelle trägt ihren Schlüssel und die volle Asset-Id. Eine voll bemalte Karte von 100 × 100 mit zwei Layern sind damit 20 000 Einträge in der Projektdatei.
Im Speicher ist die Map gewollt: Malen, Radieren und Nachbarn lesen wollen genau das. Es geht nur um die Datei.
Zu bauen
Ein kompaktes Speicherformat für die Zellen, nur in serialize.ts (Schreiben und Lesen). Das Modell im Speicher bleibt die Map.
Alte Projekte laden weiter: Das bisherige Format wird beim Laden erkannt und still übernommen, gespeichert wird im neuen.
Tests: Unit-Tests für die Hin- und Rückrichtung (leer, eine Zelle, volle Karte, mehrere Tiles, Zellen außerhalb des Rasters), Laden des alten Formats. Dazu eine Messung der Dateigröße vorher/nachher an einer großen Karte.
Offen (mit Vorschlag)
Format: Tile-Ids pro Layer einmal als Liste, die Zellen dann als Index darauf, zeilenweise lauflängenkodiert. Vorschlag: so. Gut lesbar im JSON und klein bei großen einheitlichen Flächen.
Zellen außerhalb des Rasters: Sie bleiben heute erhalten und kommen beim Vergrößern zurück. Vorschlag: im neuen Format genauso erhalten, nichts stillschweigend wegwerfen.
Wann: Erst sinnvoll, wenn Karten wirklich groß werden. Vorschlag: vorher mit einer echten Karte messen, ob es sich lohnt.
Folge-Issue zu #128, dort unter „Nicht enthalten“ aufgeführt.
## Befund
- Pro Layer werden die Zellen als Map `"x,y"` → Tile-Id gespeichert (`src/core/model/tilemap.ts:6`). Jede bemalte Zelle trägt ihren Schlüssel und die volle Asset-Id. Eine voll bemalte Karte von 100 × 100 mit zwei Layern sind damit 20 000 Einträge in der Projektdatei.
- Im Speicher ist die Map gewollt: Malen, Radieren und Nachbarn lesen wollen genau das. Es geht nur um die **Datei**.
## Zu bauen
- Ein kompaktes Speicherformat für die Zellen, nur in `serialize.ts` (Schreiben und Lesen). Das Modell im Speicher bleibt die Map.
- **Alte Projekte laden weiter:** Das bisherige Format wird beim Laden erkannt und still übernommen, gespeichert wird im neuen.
- Tests: Unit-Tests für die Hin- und Rückrichtung (leer, eine Zelle, volle Karte, mehrere Tiles, Zellen außerhalb des Rasters), Laden des alten Formats. Dazu eine Messung der Dateigröße vorher/nachher an einer großen Karte.
## Offen (mit Vorschlag)
- **Format:** Tile-Ids pro Layer einmal als Liste, die Zellen dann als Index darauf, zeilenweise lauflängenkodiert. Vorschlag: so. Gut lesbar im JSON und klein bei großen einheitlichen Flächen.
- **Zellen außerhalb des Rasters:** Sie bleiben heute erhalten und kommen beim Vergrößern zurück. Vorschlag: im neuen Format genauso erhalten, nichts stillschweigend wegwerfen.
- **Wann:** Erst sinnvoll, wenn Karten wirklich groß werden. Vorschlag: vorher mit einer echten Karte messen, ob es sich lohnt.
Ein String pro Zeile statt Zahlen-Arrays — wegen JSON_PRETTY_PRINT stünde sonst jede Zahl auf einer eigenen Zeile.
index zählt ab 1 in tiles, 0 ist leer; *1 entfällt, leere Zellen am Zeilenende werden nicht geschrieben.
Zellen außerhalb des Rasters bleiben erhalten (das Rechteck kommt aus den bemalten Zellen, negative Koordinaten gehen).
Im Speicher bleibt die Map; geändert ist nur serialize.ts, der Kodierer liegt in src/core/store/tilemapCells.ts.
Alte Projekte mit cells laden weiter und werden beim nächsten Speichern umgeschrieben.
Nachsichtiges Lesen: ein kaputter Lauf beendet seine Zeile, ein Index ohne Tile gilt als leer, ein Lauf ist höchstens 65 536 lang.
Tests (lokal)
npm run check → 97 Files, 1323 Tests (vorher 1309), CHECK EXIT 0
npm run build → BUILD EXIT 0
GM_STEPS=1-16,24,25,33,36,38,39,40 (frisch geseedet) → ALL PASSED – 587 checks
14 neue Unit-Tests (tests/core/tilemap-cells.test.ts): Rundwege (leer, einzeln, Lücken, außerhalb des Rasters, volle 100er-Karte, 500 Zufallszellen), Map bleibt unverändert, altes Format lesen/neu schreiben, Größenschranke, vier Fälle nachsichtiges Lesen.
Gegenprobe mit 4 absichtlichen Fehlern, alle gefangen: Index um eins verschoben (11 rot), Lücke zu kurz (4), keine Laufobergrenze (1), neues Format beim Laden ignoriert (3).
e2e Modul 40, Schritt 40k: speichern, Datei vom Server lesen (keine cells, dafür tiles/rows), neu laden, Zellen identisch. +4 Checks.
Doku
Wiki Tilemaps.md mit neuem Abschnitt In the project file, Architecture.md (Store-Zeile), Development.md. Check-Summe 1017 in README und Wiki — gerechnet, CI steht noch aus.
Erledigt in `10b49fa`, Wiki `a0f279a`.
## Lohnt es sich?
Vor dem Bauen gemessen, pretty-printed wie der Server schreibt:
| Karte | vorher | nachher |
|---|---|---|
| echte Karte (3 Layer, 445 Zellen) | 15 396 B | 1 154 B |
| 100 × 100, 2 Layer, einer gesprenkelt | 736 084 B | 10 964 B |
## Format
Umgesetzt wie vorgeschlagen, pro Layer:
```json
"tiles": ["grass", "path"],
"origin": { "x": 0, "y": 0 },
"rows": ["1*40 0*3 2", "1*44"]
```
- Ein String pro Zeile statt Zahlen-Arrays — wegen `JSON_PRETTY_PRINT` stünde sonst jede Zahl auf einer eigenen Zeile.
- `index` zählt ab 1 in `tiles`, `0` ist leer; `*1` entfällt, leere Zellen am Zeilenende werden nicht geschrieben.
- Zellen außerhalb des Rasters bleiben erhalten (das Rechteck kommt aus den bemalten Zellen, negative Koordinaten gehen).
- Im Speicher bleibt die Map; geändert ist nur `serialize.ts`, der Kodierer liegt in `src/core/store/tilemapCells.ts`.
- Alte Projekte mit `cells` laden weiter und werden beim nächsten Speichern umgeschrieben.
- Nachsichtiges Lesen: ein kaputter Lauf beendet seine Zeile, ein Index ohne Tile gilt als leer, ein Lauf ist höchstens 65 536 lang.
## Tests (lokal)
```
npm run check → 97 Files, 1323 Tests (vorher 1309), CHECK EXIT 0
npm run build → BUILD EXIT 0
GM_STEPS=1-16,24,25,33,36,38,39,40 (frisch geseedet) → ALL PASSED – 587 checks
```
- 14 neue Unit-Tests (`tests/core/tilemap-cells.test.ts`): Rundwege (leer, einzeln, Lücken, außerhalb des Rasters, volle 100er-Karte, 500 Zufallszellen), Map bleibt unverändert, altes Format lesen/neu schreiben, Größenschranke, vier Fälle nachsichtiges Lesen.
- Gegenprobe mit 4 absichtlichen Fehlern, alle gefangen: Index um eins verschoben (11 rot), Lücke zu kurz (4), keine Laufobergrenze (1), neues Format beim Laden ignoriert (3).
- e2e Modul 40, Schritt 40k: speichern, Datei vom Server lesen (keine `cells`, dafür `tiles`/`rows`), neu laden, Zellen identisch. +4 Checks.
## Doku
Wiki `Tilemaps.md` mit neuem Abschnitt *In the project file*, `Architecture.md` (Store-Zeile), `Development.md`. Check-Summe **1017** in README und Wiki — gerechnet, CI steht noch aus.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Folge-Issue zu #128, dort unter „Nicht enthalten“ aufgeführt.
Befund
"x,y"→ Tile-Id gespeichert (src/core/model/tilemap.ts:6). Jede bemalte Zelle trägt ihren Schlüssel und die volle Asset-Id. Eine voll bemalte Karte von 100 × 100 mit zwei Layern sind damit 20 000 Einträge in der Projektdatei.Zu bauen
serialize.ts(Schreiben und Lesen). Das Modell im Speicher bleibt die Map.Offen (mit Vorschlag)
Erledigt in
10b49fa, Wikia0f279a.Lohnt es sich?
Vor dem Bauen gemessen, pretty-printed wie der Server schreibt:
Format
Umgesetzt wie vorgeschlagen, pro Layer:
JSON_PRETTY_PRINTstünde sonst jede Zahl auf einer eigenen Zeile.indexzählt ab 1 intiles,0ist leer;*1entfällt, leere Zellen am Zeilenende werden nicht geschrieben.serialize.ts, der Kodierer liegt insrc/core/store/tilemapCells.ts.cellsladen weiter und werden beim nächsten Speichern umgeschrieben.Tests (lokal)
tests/core/tilemap-cells.test.ts): Rundwege (leer, einzeln, Lücken, außerhalb des Rasters, volle 100er-Karte, 500 Zufallszellen), Map bleibt unverändert, altes Format lesen/neu schreiben, Größenschranke, vier Fälle nachsichtiges Lesen.cells, dafürtiles/rows), neu laden, Zellen identisch. +4 Checks.Doku
Wiki
Tilemaps.mdmit neuem Abschnitt In the project file,Architecture.md(Store-Zeile),Development.md. Check-Summe 1017 in README und Wiki — gerechnet, CI steht noch aus.