# Lua State Persistence / Spielstand-Speicherung ## Übersicht Der Wherigo Player kann den Lua-State speichern und wiederherstellen, um Spielfortschritte zu sichern. ## Funktionsweise ### Automatisches Speichern Der Spielstand wird automatisch gespeichert unter: - **macOS**: `~/Library/Application Support/wxWherigo/.save` - **Windows**: `%APPDATA%\wxWherigo\.save` - **Linux**: `~/.wxWherigo/.save` ### Was wird gespeichert? Die Persistierung speichert: - ✅ **Alle Wherigo-Objekte**: ZCartridge, Zone, ZItem, ZCharacter, ZTask, ZTimer, ZInput, ZMedia - ✅ **Objekt-Properties**: Name, Description, Active, Visible, Container, etc. - ✅ **Globale Variablen**: Alle einfachen Variablen (Strings, Numbers, Booleans) - ✅ **Player-Objekt**: Position, Inventar, etc. - ✅ **Verschachtelte Tabellen**: Rekursive Serialisierung (bis Tiefe 10) ### Was wird NICHT gespeichert? - ❌ **Funktionen**: Lua-Funktionen können nicht serialisiert werden - ❌ **Userdata**: C-Objekte bleiben im Originalzustand - ❌ **Threads/Coroutines**: Werden als `nil` gespeichert - ❌ **Metatables**: Werden nicht persistent gespeichert ## Verwendung im Code ### Spielstand speichern ```cpp // Automatischer Pfad (empfohlen) wxGetApp().saveGameState(""); // Eigener Pfad wxGetApp().saveGameState("/path/to/save.lua"); ``` ### Spielstand laden ```cpp // Automatischer Pfad wxGetApp().loadGameState(""); // Eigener Pfad wxGetApp().loadGameState("/path/to/save.lua"); ``` ### Im Spiel - **Menü → Spielstand speichern** (Strg+S) - **Menü → Spielstand laden** (Strg+L) ## Save-Datei-Format Die Save-Datei ist eine lesbare Lua-Datei: ```lua -- Wherigo Save State return { ["Player"] = { ["ClassName"] = "Player", ["Name"] = "Player", ["ObjectLocation"] = { ["latitude"] = 51.5074, ["longitude"] = -0.1278, ["altitude"] = 0 } }, ["zitemLetter"] = { ["ClassName"] = "ZItem", ["Name"] = "Letter from Professor", ["Active"] = true, ["Visible"] = true, ["Container"] = }, -- ... weitere Objekte } ``` ## Technische Details ### Serialisierung Die Implementierung verwendet: 1. **Rekursives Traversieren** der Lua-Tabellen 2. **Type-Detection** für verschiedene Lua-Typen 3. **Escaping** von Sonderzeichen in Strings 4. **Referenz-Handling** durch Lua selbst beim Laden ### Deserialisierung 1. Save-Datei wird als Lua-Code geladen (`luaL_loadstring`) 2. Ausführung gibt eine Tabelle zurück (`lua_pcall`) 3. Tabellen-Einträge werden als Globals wiederhergestellt 4. UI wird über `notifyStateChanged()` aktualisiert ## Performance - **Speichern**: ~10-100ms für typische Cartridges - **Laden**: ~20-200ms (inkl. Lua-Parsing) - **Dateigröße**: ~10-500KB (abhängig von Cartridge-Komplexität) ## Erweiterungen ### Eigene Filter ```cpp // Nur bestimmte Globals speichern std::vector myGlobals = {"Player", "zitemKey", "ztaskMain"}; wherigo::LuaPersistence::saveGlobals(L, "custom.save", myGlobals); ``` ### Auto-Save beim Beenden ```cpp // In cGame::OnClose() wxGetApp().saveGameState(""); // Auto-Save ``` ### Mehrere Save-Slots ```cpp std::string slot1 = wxGetApp().getAutoSavePath() + ".slot1"; std::string slot2 = wxGetApp().getAutoSavePath() + ".slot2"; std::string slot3 = wxGetApp().getAutoSavePath() + ".slot3"; ``` ## Bekannte Limitierungen 1. **Funktions-Callbacks** werden nicht gespeichert (OnClick, OnEnter, etc.) - Diese bleiben im Cartridge-Code definiert 2. **Zirkuläre Referenzen** werden bei der Rekursion abgebrochen - Max. Tiefe: 10 Ebenen 3. **Metatables** gehen verloren - Nach dem Laden müssen ggf. Metatables neu gesetzt werden 4. **Timer-Status** wird gespeichert, aber `Remaining` muss ggf. neu berechnet werden ## Debugging Aktiviere Logging um Save/Load zu tracken: ```cpp wxLogDebug("Saved %zu globals to %s", globals.size(), filePath); wxLogDebug("Restored %d globals from %s", count, filePath); ``` ## Zukünftige Erweiterungen Mögliche Verbesserungen: - [ ] Kompression der Save-Dateien (zlib) - [ ] Verschlüsselung (verhindert Cheating) - [ ] Delta-Saves (nur Änderungen speichern) - [ ] Cloud-Sync Integration - [ ] Automatisches Backup (3 neueste Saves)