feat(save): Speicherstand als Game-Baum
Autosave beim Betreten einer Etage und beim Beenden, ein Slot, bei Tod geloescht. Der Save ist der Baum selbst — keine eigenen Save-Structs, die man zweimal pflegt. - Kacheln als ASCII-Zeilen wie ein Prefab, nicht 3200 Enum-Eintraege - atomar geschrieben: tmp plus rename, der einzige Stand ueberlebt einen Abbruch - fremdes Schema wird abgelehnt, die Datei bleibt liegen - fehlende Mods verwerfen Eintraege, nie den Lauf - Confirm-Screen vor dem Spiel, wenn der Save Eintraege verloren hat Fuenf Befunde: die Ereigniswarteschlange gehoert nicht in den Save, die Feldreihenfolge ist Teil des TOML-Formats, Serialize fuer Floor muss von Hand, Confirm braucht on_no, und die Rueckfrage galt zuerst auch fuer Mod-Ladewarnungen.
This commit is contained in:
@@ -147,3 +147,36 @@ nie eine halbe.
|
||||
|---|---|
|
||||
| **02** | **`core:attack` und `core:flee` sind jedem Wesen implizit gewährt.** Fähigkeiten kommen bisher ausschließlich von Charakteroptionen und Gegenständen — ein Held, dessen Klasse fehlt und der nichts trägt, hätte gar keine und könnte nicht einmal angreifen. Das ist keine Sonderregel für den Ladefall: Auch jeder Gegner ohne `abilities`-Eintrag trifft es, und die KI aus 14 stünde vor einer leeren Liste |
|
||||
| **11** | `Confirm { text, on_yes: Box<Response> }` statt `on_yes: Command`. Die Rückfrage beim Laden braucht keinen Command, sondern einen Screen-Wechsel. `Response::Command` ist bereits eine Variante, der bisherige Fall bleibt also erhalten — der Sonderfall entfällt ersatzlos, die Struktur wird dabei *kleiner* |
|
||||
|
||||
### Befunde aus M6
|
||||
|
||||
**Die Ereigniswarteschlange gehört nicht in den Save.** „Der Kampfzustand fällt bei serde-Ableitung
|
||||
gratis mit ab" stimmt für `enemies`, `initiative` und `cooldowns` — nicht für `Game.events`. Die ist
|
||||
Zwischenstand *innerhalb* eines Zuges: `drain_events` leert sie nach jeder einzelnen Handlung, und
|
||||
gespeichert wird ausschließlich zwischen Zügen. Sie mitzuschreiben hieße, immer eine leere Liste zu
|
||||
speichern. Sie steht jetzt auf `#[serde(skip)]`, mit einem `debug_assert` in `save()`, das die
|
||||
Behauptung festhält statt sie nur zu behaupten.
|
||||
|
||||
Angenehmer Nebeneffekt: Ohne `events` taucht `CreatureRef` im Save gar nicht auf — und damit auch kein
|
||||
`{ Enemy = 3 }` als Inline-Tabelle in einer Datei, die lesbar sein soll.
|
||||
|
||||
**Die Feldreihenfolge ist Teil des Formats.** TOML verlangt Werte vor Tabellen. „Der Save *ist* der
|
||||
Baum" heißt deshalb: Die Reihenfolge der Felder in `Game`, `Creature`, `Room` und `Floor` ist keine
|
||||
Kosmetik mehr, sondern eine Bedingung. `Game`, `Creature` und `Room` mussten umsortiert werden — alles
|
||||
Skalare nach oben, alles Verschachtelte nach unten. Der Rundlauf-Test fällt sofort um, wenn jemand das
|
||||
wieder vermischt; das ist die einzige Absicherung, die es dafür gibt.
|
||||
|
||||
**`Serialize` für `Floor` muss von Hand.** Der Zeilenumbruch im Kachelgitter braucht die Breite, und
|
||||
ein feldweises `#[serde(with = …)]` sieht nur sein eigenes Feld. `Deserialize` bleibt abgeleitet (die
|
||||
Zeilen werden einfach aneinandergehängt), `Serialize` sind fünfzehn Zeilen. Das ist genau die eine
|
||||
handgeschriebene Ausnahme, die das Ticket vorgesehen hat — nur an einer anderen Stelle als gedacht.
|
||||
|
||||
**Die Rückfrage braucht `on_no`.** Ticket 11 hatte `Confirm { text, on_yes: Box<Response> }` beschlossen
|
||||
und „Nein" implizit als Wegklicken gedacht. Im Ladefall heißt Nein aber *beenden und den Mod
|
||||
nachinstallieren* — genau die Wahl, die es nach dem Laden nicht mehr gibt. `on_no` ist ein Feld mehr
|
||||
und spart eine ungeschriebene Regel.
|
||||
|
||||
**Die Rückfrage gilt nur für Verworfenes aus dem Save.** Beim ersten Bauen hing sie an *allen*
|
||||
Warnungen, also auch an denen des Mod-Ladelaufs — und damit hätte ein kaputter TOML-Eintrag in einem
|
||||
Mod den Start blockiert. Ticket 04 hat dafür ausdrücklich „eine Zeile, kein Screen" entschieden. Beide
|
||||
Zahlen werden jetzt getrennt gezählt, obwohl beide in dieselbe Logdatei laufen.
|
||||
|
||||
Reference in New Issue
Block a user