docs: ticket 03 (mod-ladepipeline) aufloesen, mod ins glossar, vorgaben an tickets 04 und 10
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
# 03 — Mod-Ladepipeline und Manifest
|
# 03 — Mod-Ladepipeline und Manifest
|
||||||
|
|
||||||
Type: grilling
|
Type: grilling
|
||||||
Status: open
|
Status: resolved
|
||||||
Blocked by: 02
|
Blocked by: 02
|
||||||
|
|
||||||
## Question
|
## Question
|
||||||
@@ -18,3 +18,146 @@ Das Kernspiel ist `core:` und damit selbst ein Mod. Zu klären:
|
|||||||
- Wird beim Start alles geladen, oder gibt es ein Nachladen zur Laufzeit?
|
- Wird beim Start alles geladen, oder gibt es ein Nachladen zur Laufzeit?
|
||||||
|
|
||||||
Ergebnis: Ordnerlayout, Manifest-Schema und die Phasen der Ladepipeline.
|
Ergebnis: Ordnerlayout, Manifest-Schema und die Phasen der Ladepipeline.
|
||||||
|
|
||||||
|
## Answer
|
||||||
|
|
||||||
|
Begriffe im [Glossar](../../../CONTEXT.md).
|
||||||
|
|
||||||
|
### Ordnerlayout — zwei Suchpfade
|
||||||
|
|
||||||
|
`mods/` neben der Binary ist die Auslieferung und enthält `core/`. `data_dir()/rustkeep/mods` im
|
||||||
|
Benutzerprofil ist der Ort, an dem die Mods des Spielers eine Neuinstallation überleben. Der Pfad
|
||||||
|
kommt aus der Crate `directories` (6.0.0) — acht handgerollte Zeilen hätten Windows und Linux
|
||||||
|
bedient, `directories` nimmt macOS mit.
|
||||||
|
|
||||||
|
Liegt dieselbe Mod-ID in beiden Pfaden, **gewinnt das Profil**, mit Warnzeile. Das ist die Richtung,
|
||||||
|
in die der zweite Pfad zeigt: Er existiert, damit die Sachen des Spielers bleiben, und dann darf die
|
||||||
|
Neuinstallation sie nicht stumm überstimmen. Es gilt auch für `core` — überschreibbar und
|
||||||
|
protokolliert. Die Warnzeile ist die einzige Diagnose, die je zwischen „mein Mod tut nichts" und
|
||||||
|
einer vergessenen alten Kopie im Profil unterscheidet.
|
||||||
|
|
||||||
|
**`core` ist ein gewöhnlicher Mod-Ordner auf der Platte**, kein privilegierter Sonderfall.
|
||||||
|
`include_str!` entfällt. Bliebe das Kernspiel einkompiliert, wäre die Mod-Fähigkeit nie getestet und
|
||||||
|
jeder Bug im Lader träfe ausschließlich die Modder.
|
||||||
|
|
||||||
|
`load_order.toml` liegt ebenfalls in `data_dir()`. Die XDG-Trennung von Daten und Konfiguration
|
||||||
|
kostet einen zweiten Pfad, einen zweiten „existiert nicht"-Fall und einen Ordner, den der Spieler
|
||||||
|
suchen muss — für eine einzelne Textdatei.
|
||||||
|
|
||||||
|
### Manifest — `manifest.toml`, Pflicht
|
||||||
|
|
||||||
|
```toml
|
||||||
|
id = "meinmod" # Namensraum-Präfix und Mod-ID, unabhängig vom Ordnernamen
|
||||||
|
name = "Mein Mod"
|
||||||
|
version = "1.0.0"
|
||||||
|
depends = ["core"] # nur Namen, keine Versionsbereiche
|
||||||
|
```
|
||||||
|
|
||||||
|
TOML, nicht YAML: `serde_yaml` ist seit dem 25.03.2024 archiviert und unmaintained, der
|
||||||
|
Nachfolge-Fork `serde_yml` ebenfalls — nach einer Unsoundness im Serializer (RUSTSEC-2025-0068).
|
||||||
|
Übrig bleiben junge Crates (`serde-saphyr`, `noyalib`, `yaml-rust2`). Für den Parser, der bei
|
||||||
|
*jedem* Mod als erstes läuft, ist das eine schlechtere Basis als das ohnehin vorhandene `toml`.
|
||||||
|
Dazu käme eine zweite Fehlermeldungssprache, die Ticket 04 mit abfangen müsste. YAMLs Stärke ist
|
||||||
|
tiefe Verschachtelung; das Manifest hat vier flache Felder.
|
||||||
|
|
||||||
|
`id` ist unabhängig vom Ordnernamen — das Manifest ist die Quelle, und Phase 1 liest ohnehin alle
|
||||||
|
Manifeste, bevor sortiert wird. `depends` trägt keine Versionsbereiche: Semver-Matching ist ein
|
||||||
|
Parser plus eine Konfliktauflösung für ein Problem, das erst existiert, wenn zwei Versionen desselben
|
||||||
|
Mods im Umlauf sind. `version` ist bis dahin Anzeige und Save-Header. `description` und `author`
|
||||||
|
kommen, wenn es einen Mod-Screen gibt, der sie anzeigt.
|
||||||
|
|
||||||
|
Ein Ordner ohne Manifest ist kein Mod: Warnzeile, übersprungen, kein Fehler — sonst legt eine
|
||||||
|
vergessene `screenshots/`-Kopie das Spiel lahm.
|
||||||
|
|
||||||
|
### Ladereihenfolge — Spielerliste, nicht Topo-Sort
|
||||||
|
|
||||||
|
`load_order.toml` listet Manifest-IDs in Reihenfolge und ist selbstheilend:
|
||||||
|
|
||||||
|
| Fall | Verhalten |
|
||||||
|
|---|---|
|
||||||
|
| Datei fehlt | wird erzeugt: `core` zuerst, Rest alphabetisch |
|
||||||
|
| Ordner auf der Platte, nicht in der Liste | hinten angehängt, Datei zurückgeschrieben |
|
||||||
|
| Eintrag in der Liste, kein Ordner | Warnzeile, übersprungen |
|
||||||
|
|
||||||
|
Ein entpackter Mod läuft damit, ohne dass der Spieler von der Existenz der Sortierdatei weiß, und
|
||||||
|
ein deinstallierter hindert das Spiel nicht am Start. Kein Sortier-Screen für 1.0 — die Datei *ist*
|
||||||
|
die UI.
|
||||||
|
|
||||||
|
**`depends` sortiert nicht, es prüft.** Fehlende Abhängigkeit oder falsche Position sind harte
|
||||||
|
Startfehler im Klartext: „`meinmod` muss nach `magiemod` geladen werden, steht aber davor". Das ist
|
||||||
|
der Preis dafür, dass ein Mensch die Reihenfolge pflegt — ohne die Prüfung merkt er den Fehler erst
|
||||||
|
an einer Meldung über eine unbekannte ID, die auf die Symptomdatei zeigt statt auf die Ursache.
|
||||||
|
Ein Mod, dessen Voraussetzung fehlt, produziert sonst zehn Folgefehler.
|
||||||
|
|
||||||
|
### Dateien im Mod
|
||||||
|
|
||||||
|
Jede `*.toml` außer dem Manifest wird eingelesen, und jede Datei darf jede Registry-Tabelle enthalten
|
||||||
|
(`[[items]]`, `[[slots]]`, `[[categories]]`, `[[options]]`, `[[abilities]]`). Keine festen
|
||||||
|
Dateinamen — der Modder sortiert selbst, und ein großer Mod muss seine 4000 Gegenstände nicht in
|
||||||
|
eine Datei zwingen.
|
||||||
|
|
||||||
|
Das ist *weniger* Code, nicht mehr: eine Struct mit fünf optionalen `Vec`-Feldern, über jede
|
||||||
|
gefundene Datei deserialisiert, Ergebnisse angehängt. Feste Namen bräuchten dieselbe Struct plus
|
||||||
|
eine Namensliste plus Antworten auf „Datei fehlt" und „unbekannte Datei liegt daneben".
|
||||||
|
|
||||||
|
### IDs und Überschreiben
|
||||||
|
|
||||||
|
Der Lader stellt `manifest.id` automatisch voran: `id = "schwert"` wird zu `meinmod:schwert`.
|
||||||
|
Überschrieben wird über ein Feld am Eintrag:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[items]]
|
||||||
|
id = "eisenschwert"
|
||||||
|
overrides = "core:iron_sword"
|
||||||
|
```
|
||||||
|
|
||||||
|
Der Eintrag landet **nur** unter `core:iron_sword`; `meinmod:eisenschwert` wird nicht registriert.
|
||||||
|
Der Zweck des Überschreibens ist, dass bestehende Verweise weiterfunktionieren — Loottabellen,
|
||||||
|
`on_create`-Startausrüstung und Questbelohnungen zeigen auf `core:iron_sword` und liefern ab sofort
|
||||||
|
das neue Schwert. Beide IDs zu registrieren hieße, denselben Gegenstand zweimal in der Welt zu haben:
|
||||||
|
doppelt im Händlerbestand, doppelt in jeder Registry-Schleife.
|
||||||
|
|
||||||
|
Zeigt `overrides` ins Leere — Zielmod nicht installiert oder vertippt —, gibt es eine Warnzeile und
|
||||||
|
der Eintrag wird verworfen. Ihn ersatzweise unter der eigenen ID zu registrieren wäre schlimmer als
|
||||||
|
nichts zu tun: Der Modder wollte etwas ersetzen und bekäme stumm einen zusätzlichen Gegenstand
|
||||||
|
in die Welt gelegt.
|
||||||
|
|
||||||
|
Überschreiben zwei Mods dasselbe, entscheidet die Ladereihenfolge — der letzte gewinnt. `overrides`
|
||||||
|
ist ein Feld an *jedem* Registry-Eintrag, nicht nur an Gegenständen.
|
||||||
|
|
||||||
|
### Drei Phasen
|
||||||
|
|
||||||
|
1. **Manifeste** — alle Ordner beider Pfade scannen, `manifest.toml` lesen, Reihenfolge aus
|
||||||
|
`load_order.toml` bestimmen, `depends` prüfen.
|
||||||
|
2. **Einlesen** — alle Dateien in Ladereihenfolge, Einträge nach ID in die Registries, spätere
|
||||||
|
überschreiben frühere. Hier wird *nichts* aufgelöst. Dadurch gibt es keine Vorwärtsreferenzen:
|
||||||
|
Ein Mod darf auf etwas zeigen, das erst ein späterer liefert.
|
||||||
|
3. **Auflösen** — alle Referenzen prüfen: Gegenstand → Slot, Charakteroption → Fähigkeit,
|
||||||
|
Aktion → Gegenstand.
|
||||||
|
|
||||||
|
**Fehlereinheit ist der einzelne Eintrag**, nicht der Mod und nicht das Spiel. Ein Tippfehler in
|
||||||
|
einem von 200 Gegenständen darf die anderen 199 nicht mitreißen — beim Kernspiel wäre es der
|
||||||
|
Totalausfall. Was genau eine kaputte Referenz auslöst, entscheidet Ticket 04.
|
||||||
|
|
||||||
|
**Kein Nachladen zur Laufzeit.** Nachladen hieße, dass jede laufende Referenz auf einen
|
||||||
|
Registry-Eintrag ungültig werden kann, mitten im Kampf — das ist kein Feature, sondern eine
|
||||||
|
Invalidierungs-Architektur, die den `Game`-Baum aus Ticket 07 mitbestimmt. Neustart ist die
|
||||||
|
Reload-Taste, und ein Terminalspiel startet in Millisekunden.
|
||||||
|
|
||||||
|
### Auflagen an andere Tickets
|
||||||
|
|
||||||
|
- **04 Fehlerstrategie**: erbt den Katalog Warnung-vs-Abbruch. Die harten Fälle stehen fest —
|
||||||
|
`depends` fehlend oder verletzt. Alles andere ist bislang Warnung plus Eintrag verwerfen; 04 muss
|
||||||
|
das zu einer Regel machen und entscheiden, wo die Warnungen landen, wenn der Bildschirm ratatui
|
||||||
|
gehört.
|
||||||
|
- **09 Save-Schema**: Der Mod-Header nutzt `manifest.id` und `version`. Ohne Versionsbereiche in
|
||||||
|
`depends` ist `version` dort das einzige Signal, dass ein Mod sich geändert hat — und damit
|
||||||
|
09 zugleich sein *einziger* Leser in 1.0. Fällt der Header, fällt das Feld mit.
|
||||||
|
- **10 Raum-Prefab-Format**: Prefabs sind eine weitere Registry über dieselbe Pipeline, kein eigener
|
||||||
|
Lader — sie erben Namensraum, `overrides` und die drei Phasen.
|
||||||
|
|
||||||
|
### Folgen für bestehenden Code
|
||||||
|
|
||||||
|
`include_str!` und `load_items()` entfallen zugunsten des Mod-Laders. `mods/core/` entsteht,
|
||||||
|
`weapons.toml` und `armors.toml` ziehen dorthin (verschmolzen laut Ticket 02). `directories` kommt
|
||||||
|
als Dependency in `Cargo.toml`.
|
||||||
|
|||||||
@@ -21,3 +21,14 @@ ist fehlerhaftes TOML der Normalfall, nicht der Ausnahmefall. Zu klären:
|
|||||||
- Wie kommt die Herkunft in die Meldung — Datei, Zeile, Mod-ID?
|
- Wie kommt die Herkunft in die Meldung — Datei, Zeile, Mod-ID?
|
||||||
|
|
||||||
Ergebnis: Fehlerklassifikation, Reaktion je Klasse, und die gewählte Rust-Fehlerbehandlung mit Begründung.
|
Ergebnis: Fehlerklassifikation, Reaktion je Klasse, und die gewählte Rust-Fehlerbehandlung mit Begründung.
|
||||||
|
|
||||||
|
## Vorgabe aus Ticket 03
|
||||||
|
|
||||||
|
[Ticket 03](03-mod-ladepipeline.md) klassifiziert seine eigenen Fälle bereits durch: **hart** ist
|
||||||
|
allein `depends` fehlend oder in der Reihenfolge verletzt, alles Übrige ist Warnung plus Überspringen.
|
||||||
|
**Fehlereinheit ist der einzelne Eintrag**, nicht der Mod und nicht das Spiel.
|
||||||
|
|
||||||
|
Offen bleibt damit: kaputte TOML-Syntax (die Datei ist unlesbar, die Einheit „Eintrag" greift nicht),
|
||||||
|
fehlende Pflichtfelder, unaufgelöste Referenzen aus Phase 3 — und wohin die Warnungen gehen, wenn der
|
||||||
|
Bildschirm ratatui gehört. Ein Ladelauf produziert leicht ein Dutzend, und `println!` ist nach dem
|
||||||
|
TUI-Start keine Option mehr.
|
||||||
|
|||||||
@@ -20,3 +20,10 @@ Entschieden ist der Hybrid: Modder bauen Prefabs, der Generator setzt prozedural
|
|||||||
- Wie greift ein Mod ein — nur neue Prefabs hinzufügen, oder auch Generator-Parameter ändern?
|
- Wie greift ein Mod ein — nur neue Prefabs hinzufügen, oder auch Generator-Parameter ändern?
|
||||||
|
|
||||||
Ergebnis: Prefab-Schema mit Beispiel plus die Regeln, nach denen der Generator zusammensetzt.
|
Ergebnis: Prefab-Schema mit Beispiel plus die Regeln, nach denen der Generator zusammensetzt.
|
||||||
|
|
||||||
|
## Vorgabe aus Ticket 03
|
||||||
|
|
||||||
|
Prefabs sind eine **weitere Registry über dieselbe Ladepipeline**, kein eigener Lader — das
|
||||||
|
beantwortet die letzte Frage oben halb: Hinzufügen ist der Normalfall, Ersetzen geht über `overrides`.
|
||||||
|
Offen bleibt, ob **Generator-Parameter** (Etagen-Tabellen, Gewichtungen, Pflichträume) ebenfalls
|
||||||
|
Registry-Einträge sind — dann mit derselben Maschine moddbar — oder ein Sonderfall.
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ Feststehende Rahmenentscheidungen aus der Charter-Session:
|
|||||||
| Rendering | ratatui + crossterm; `print_box` fliegt raus, sobald ratatui steht |
|
| Rendering | ratatui + crossterm; `print_box` fliegt raus, sobald ratatui steht |
|
||||||
| Etagen | Hybrid — Raum-Prefabs in TOML, prozedural zusammengesetzt |
|
| Etagen | Hybrid — Raum-Prefabs in TOML, prozedural zusammengesetzt |
|
||||||
| Daten | Alles TOML, zur Laufzeit geladen. `include_str!` und `enum ItemType` fallen |
|
| Daten | Alles TOML, zur Laufzeit geladen. `include_str!` und `enum ItemType` fallen |
|
||||||
| Mod-IDs | Namespaced (`core:iron_sword`), Ladereihenfolge aus Mod-Manifest. Das Kernspiel ist selbst ein Mod |
|
| Mod-IDs | Namespaced (`core:iron_sword`), Präfix aus dem Manifest und automatisch vorangestellt. Ladereihenfolge aus einer Spielerliste, nicht aus dem Manifest (03). Das Kernspiel ist selbst ein Mod |
|
||||||
| Mod-Stufen | Daten → Typen → Scripting, in dieser Reihenfolge. Scripting setzt auf der Typ-Registry auf |
|
| Mod-Stufen | Daten → Typen → Scripting, in dieser Reihenfolge. Scripting setzt auf der Typ-Registry auf |
|
||||||
| Effekte | Ein generisches Effekt-System mit Wirkung auf Stats. Rasse, Klasse, Items, Statuseffekte, Quest-Belohnungen und später Scripts nutzen dasselbe Vokabular — dieses Vokabular *ist* die Mod-API |
|
| Effekte | Ein generisches Effekt-System mit Wirkung auf Stats. Rasse, Klasse, Items, Statuseffekte, Quest-Belohnungen und später Scripts nutzen dasselbe Vokabular — dieses Vokabular *ist* die Mod-API |
|
||||||
| Quests | Bedingung + Belohnung als Daten, generisches Event-/Trigger-System |
|
| Quests | Bedingung + Belohnung als Daten, generisches Event-/Trigger-System |
|
||||||
@@ -61,6 +61,7 @@ auch über Ticket 13.
|
|||||||
|
|
||||||
- [01 — Effekt-Vokabular](issues/01-effekt-vokabular.md) ([#2](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/2)) — **Zwei Begriffe statt einem**: Modifikator (rechnet ein Attribut um, solange er existiert) und Aktion (ändert Zustand einmalig), getrennte Maschinen und getrennte TOML-Arrays. Fester Attributkatalog ohne Namensraum; `max_health` ist Attribut, der Lebensstand ist Zustand. Sechs Aktionen, `damage` eigenständig wegen der Minderungskette. Stapeln `(Basis + Σ flach) × (1 + Σ prozentual)`. Eine Uhr: der Zug. Sieben feste Schadenstypen, ein Minderungsmechanismus (`resistance`), `armor` nur Kurzschreibweise. Auren wohnen beim Träger. Bedingungsvokabular bewusst an Ticket 08 delegiert. Begriffe im [Glossar](../../CONTEXT.md).
|
- [01 — Effekt-Vokabular](issues/01-effekt-vokabular.md) ([#2](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/2)) — **Zwei Begriffe statt einem**: Modifikator (rechnet ein Attribut um, solange er existiert) und Aktion (ändert Zustand einmalig), getrennte Maschinen und getrennte TOML-Arrays. Fester Attributkatalog ohne Namensraum; `max_health` ist Attribut, der Lebensstand ist Zustand. Sechs Aktionen, `damage` eigenständig wegen der Minderungskette. Stapeln `(Basis + Σ flach) × (1 + Σ prozentual)`. Eine Uhr: der Zug. Sieben feste Schadenstypen, ein Minderungsmechanismus (`resistance`), `armor` nur Kurzschreibweise. Auren wohnen beim Träger. Bedingungsvokabular bewusst an Ticket 08 delegiert. Begriffe im [Glossar](../../CONTEXT.md).
|
||||||
- [02 — Typ-Registry statt Enums](issues/02-typ-registry.md) ([#3](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/3)) — **Es gibt keinen Item-Typ mehr**: `enum ItemType` vermischte Slot, Verhalten und Kategorie und entfällt ersatzlos zugunsten der Felder `slot`, `stackable`, `consumed_on_use`. `ItemWeapon` und `ItemArmor` fallen weg, ein Gegenstand ist einheitlich. **Fähigkeit** kommt als dritter Begriff neben Modifikator und Aktion dazu (Angebot statt Wirkung). Fünf moddbare Registries; Slots und sogar Charakteroption-Kategorien sind Inhalt, mit `pick = N`. Startausrüstung ist `on_create` als gewöhnliche Aktionsliste. `value` → `base_price`, `shop_price` → `price_modifier`.
|
- [02 — Typ-Registry statt Enums](issues/02-typ-registry.md) ([#3](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/3)) — **Es gibt keinen Item-Typ mehr**: `enum ItemType` vermischte Slot, Verhalten und Kategorie und entfällt ersatzlos zugunsten der Felder `slot`, `stackable`, `consumed_on_use`. `ItemWeapon` und `ItemArmor` fallen weg, ein Gegenstand ist einheitlich. **Fähigkeit** kommt als dritter Begriff neben Modifikator und Aktion dazu (Angebot statt Wirkung). Fünf moddbare Registries; Slots und sogar Charakteroption-Kategorien sind Inhalt, mit `pick = N`. Startausrüstung ist `on_create` als gewöhnliche Aktionsliste. `value` → `base_price`, `shop_price` → `price_modifier`.
|
||||||
|
- [03 — Mod-Ladepipeline und Manifest](issues/03-mod-ladepipeline.md) ([#4](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/4)) — Zwei Suchpfade: `mods/` neben der Binary (enthält `core/`) und `data_dir()/rustkeep/mods` über die Crate `directories`; bei gleicher ID gewinnt das Profil, mit Warnzeile. **`core` liegt als echter Mod-Ordner auf der Platte, `include_str!` entfällt.** `manifest.toml` mit vier Feldern (`id`, `name`, `version`, `depends`) — TOML statt YAML, weil `serde_yaml` und der Fork `serde_yml` beide archiviert sind. Ladereihenfolge aus einer selbstheilenden Spielerliste `load_order.toml`; `depends` sortiert nicht, sondern prüft, und eine Verletzung ist harter Startfehler. Jede `*.toml` im Mod wird eingelesen, jede darf jede Registry-Tabelle enthalten. Präfix wird automatisch vorangestellt, Überschreiben über `overrides = "core:iron_sword"` am Eintrag — der landet **nur** unter der überschriebenen ID. Drei Phasen (Manifeste → Einlesen → Auflösen), dadurch keine Vorwärtsreferenzen; Fehlereinheit ist der Eintrag. Kein Nachladen zur Laufzeit.
|
||||||
- [05 — Research: Script-Engine](issues/05-research-script-engine.md) ([#6](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/6)) — Empfehlung Rhai wegen Fehlermeldungen mit Zeile und Spalte, billiger Typ-Brücke, AST-Hot-Reload und Build ohne `cc`. Gemessen: mlua liest unter `StdLib::ALL_SAFE` per `io.open` echte Dateien — „safe" heißt dort speichersicher, nicht fähigkeitsbeschränkt. Lua gewinnt bei der Modder-Vertrautheit; WASM scheidet für 1.0 aus. **Kernfolge: reden Scripts nur über das Effekt-Vokabular, ist die Engine-Wahl umkehrbar.** Entscheidung offen in Ticket 13.
|
- [05 — Research: Script-Engine](issues/05-research-script-engine.md) ([#6](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/6)) — Empfehlung Rhai wegen Fehlermeldungen mit Zeile und Spalte, billiger Typ-Brücke, AST-Hot-Reload und Build ohne `cc`. Gemessen: mlua liest unter `StdLib::ALL_SAFE` per `io.open` echte Dateien — „safe" heißt dort speichersicher, nicht fähigkeitsbeschränkt. Lua gewinnt bei der Modder-Vertrautheit; WASM scheidet für 1.0 aus. **Kernfolge: reden Scripts nur über das Effekt-Vokabular, ist die Engine-Wahl umkehrbar.** Entscheidung offen in Ticket 13.
|
||||||
- [06 — Research: ratatui-App-Architektur](issues/06-research-ratatui-architektur.md) ([#7](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/7)) — Screen-Stack über zentralem `Game`-State statt Elm oder Component-Trait; `game/` bleibt ratatui-frei; Popups per `Clear` auf Sub-`Rect` statt Widget-Stack; blockierendes `event::read()` ohne Tick; Dungeon-Grid ist Eigenbau, es gibt kein Widget dafür; ratatui 0.30.2 mit MSRV 1.88; `KeyEventKind::Press`-Filter unter Windows Pflicht. Voller Bericht in [research/06](research/06-ratatui-architektur.md).
|
- [06 — Research: ratatui-App-Architektur](issues/06-research-ratatui-architektur.md) ([#7](https://gitlab.hive-brain.de/MDietermann/rustkeep/issues/7)) — Screen-Stack über zentralem `Game`-State statt Elm oder Component-Trait; `game/` bleibt ratatui-frei; Popups per `Clear` auf Sub-`Rect` statt Widget-Stack; blockierendes `event::read()` ohne Tick; Dungeon-Grid ist Eigenbau, es gibt kein Widget dafür; ratatui 0.30.2 mit MSRV 1.88; `KeyEventKind::Press`-Filter unter Windows Pflicht. Voller Bericht in [research/06](research/06-ratatui-architektur.md).
|
||||||
|
|
||||||
@@ -70,7 +71,7 @@ auch über Ticket 13.
|
|||||||
- **Boss-Design** — ob Bosse nur Gegner mit besseren Werten sind oder eigene Mechanik brauchen (Phasen, Skripte). Berührt Stufe (c) des Mod-Supports.
|
- **Boss-Design** — ob Bosse nur Gegner mit besseren Werten sind oder eigene Mechanik brauchen (Phasen, Skripte). Berührt Stufe (c) des Mod-Supports.
|
||||||
- **NPC- und Handelsmodell** — Warenbestand, Preisbildung über `charisma`, Dialogdaten. Wartet auf das Event-System (08).
|
- **NPC- und Handelsmodell** — Warenbestand, Preisbildung über `charisma`, Dialogdaten. Wartet auf das Event-System (08).
|
||||||
- **Inventar-UX** — Slots, Gewicht oder Kapazität, Sortierung, Vergleichsansicht. Wartet jetzt auf das Screen-Modell (11), nicht mehr auf 06.
|
- **Inventar-UX** — Slots, Gewicht oder Kapazität, Sortierung, Vergleichsansicht. Wartet jetzt auf das Screen-Modell (11), nicht mehr auf 06.
|
||||||
- **Mod-Verteilung** — wie Spieler an Mods kommen und ob es eine Versionsprüfung gibt. Wartet auf das Manifest-Format (03).
|
- **Mod-Verteilung** — durch 03 auf „Ordner ins Profil entpacken" geschrumpft, ohne Versionsprüfung. Offen ist nur noch, ob 1.0 mehr braucht.
|
||||||
|
|
||||||
## Out of scope
|
## Out of scope
|
||||||
|
|
||||||
|
|||||||
10
CONTEXT.md
10
CONTEXT.md
@@ -100,6 +100,16 @@ Die einzige Zeiteinheit des Spiels. Ein Feld weitergehen ist ein Zug, eine Kampf
|
|||||||
Es gibt keine getrennte Kampfrunden-Uhr: Befristete [Modifikatoren](#modifikator) ticken auch beim
|
Es gibt keine getrennte Kampfrunden-Uhr: Befristete [Modifikatoren](#modifikator) ticken auch beim
|
||||||
Erkunden, damit „ich warte den Debuff draußen ab" eine Entscheidung mit Kosten bleibt.
|
Erkunden, damit „ich warte den Debuff draußen ab" eine Entscheidung mit Kosten bleibt.
|
||||||
|
|
||||||
|
## Mod
|
||||||
|
|
||||||
|
Ein Ordner mit einer `manifest.toml` und beliebig vielen weiteren TOML-Dateien. Das Manifest gibt dem
|
||||||
|
Mod seinen **Namensraum** — den Präfix vor dem Doppelpunkt, den der Lader jeder ID darin automatisch
|
||||||
|
voranstellt.
|
||||||
|
|
||||||
|
Das Kernspiel ist ein Mod, kein Sonderfall: `core` liegt als gewöhnlicher Ordner auf der Platte und
|
||||||
|
wird über denselben Lader gelesen wie jeder Fremdmod. Genau das ist der Sinn — was nur für Fremdmods
|
||||||
|
gilt, ist nie getestet.
|
||||||
|
|
||||||
## Effekt
|
## Effekt
|
||||||
|
|
||||||
**Kein kanonischer Begriff.** Wird umgangssprachlich für [Modifikator](#modifikator) *und*
|
**Kein kanonischer Begriff.** Wird umgangssprachlich für [Modifikator](#modifikator) *und*
|
||||||
|
|||||||
Reference in New Issue
Block a user