4.2 KiB
4.2 KiB
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/<CartridgeName>.save - Windows:
%APPDATA%\wxWherigo\<CartridgeName>.save - Linux:
~/.wxWherigo/<CartridgeName>.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
nilgespeichert - ❌ Metatables: Werden nicht persistent gespeichert
Verwendung im Code
Spielstand speichern
// Automatischer Pfad (empfohlen)
wxGetApp().saveGameState("");
// Eigener Pfad
wxGetApp().saveGameState("/path/to/save.lua");
Spielstand laden
// 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:
-- 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"] = <reference to Player>
},
-- ... weitere Objekte
}
Technische Details
Serialisierung
Die Implementierung verwendet:
- Rekursives Traversieren der Lua-Tabellen
- Type-Detection für verschiedene Lua-Typen
- Escaping von Sonderzeichen in Strings
- Referenz-Handling durch Lua selbst beim Laden
Deserialisierung
- Save-Datei wird als Lua-Code geladen (
luaL_loadstring) - Ausführung gibt eine Tabelle zurück (
lua_pcall) - Tabellen-Einträge werden als Globals wiederhergestellt
- 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
// Nur bestimmte Globals speichern
std::vector<std::string> myGlobals = {"Player", "zitemKey", "ztaskMain"};
wherigo::LuaPersistence::saveGlobals(L, "custom.save", myGlobals);
Auto-Save beim Beenden
// In cGame::OnClose()
wxGetApp().saveGameState(""); // Auto-Save
Mehrere Save-Slots
std::string slot1 = wxGetApp().getAutoSavePath() + ".slot1";
std::string slot2 = wxGetApp().getAutoSavePath() + ".slot2";
std::string slot3 = wxGetApp().getAutoSavePath() + ".slot3";
Bekannte Limitierungen
-
Funktions-Callbacks werden nicht gespeichert (OnClick, OnEnter, etc.)
- Diese bleiben im Cartridge-Code definiert
-
Zirkuläre Referenzen werden bei der Rekursion abgebrochen
- Max. Tiefe: 10 Ebenen
-
Metatables gehen verloren
- Nach dem Laden müssen ggf. Metatables neu gesetzt werden
-
Timer-Status wird gespeichert, aber
Remainingmuss ggf. neu berechnet werden
Debugging
Aktiviere Logging um Save/Load zu tracken:
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)