optimize markdown files

Signed-off-by: Peter Siegmund <mars3142@noreply.mars3142.dev>
This commit is contained in:
2026-02-13 02:45:34 +01:00
parent f9c45ca81f
commit b7bee804ca
3 changed files with 221 additions and 182 deletions

View File

@@ -1,64 +1,64 @@
# Lua State Persistence / Spielstand-Speicherung # Lua State Persistence / Save Game System
## Übersicht ## Overview
Der Wherigo Player kann den Lua-State speichern und wiederherstellen, um Spielfortschritte zu sichern. The Wherigo Player can save and restore the Lua state to preserve game progress.
## Funktionsweise ## How It Works
### Automatisches Speichern ### Automatic Save Locations
Der Spielstand wird automatisch gespeichert unter: Game saves are automatically stored at:
- **macOS**: `~/Library/Application Support/wxWherigo/<CartridgeName>.save` - **macOS**: `~/Library/Application Support/wxWherigo/<CartridgeName>.save`
- **Windows**: `%APPDATA%\wxWherigo\<CartridgeName>.save` - **Windows**: `%APPDATA%\wxWherigo\<CartridgeName>.save`
- **Linux**: `~/.wxWherigo/<CartridgeName>.save` - **Linux**: `~/.wxWherigo/<CartridgeName>.save`
### Was wird gespeichert? ### What is Saved?
Die Persistierung speichert: Persistence saves:
-**Alle Wherigo-Objekte**: ZCartridge, Zone, ZItem, ZCharacter, ZTask, ZTimer, ZInput, ZMedia -**All Wherigo Objects**: ZCartridge, Zone, ZItem, ZCharacter, ZTask, ZTimer, ZInput, ZMedia
-**Objekt-Properties**: Name, Description, Active, Visible, Container, etc. -**Object Properties**: Name, Description, Active, Visible, Container, etc.
-**Globale Variablen**: Alle einfachen Variablen (Strings, Numbers, Booleans) -**Global Variables**: All simple variables (Strings, Numbers, Booleans)
-**Player-Objekt**: Position, Inventar, etc. -**Player Object**: Position, inventory, etc.
-**Verschachtelte Tabellen**: Rekursive Serialisierung (bis Tiefe 10) -**Nested Tables**: Recursive serialization (up to depth 10)
### Was wird NICHT gespeichert? ### What is NOT Saved?
-**Funktionen**: Lua-Funktionen können nicht serialisiert werden -**Functions**: Lua functions cannot be serialized
-**Userdata**: C-Objekte bleiben im Originalzustand -**Userdata**: C objects remain in original state
-**Threads/Coroutines**: Werden als `nil` gespeichert -**Threads/Coroutines**: Saved as `nil`
-**Metatables**: Werden nicht persistent gespeichert -**Metatables**: Not persisted
## Verwendung im Code ## Usage in Code
### Spielstand speichern ### Save Game State
```cpp ```cpp
// Automatischer Pfad (empfohlen) // Automatic path (recommended)
wxGetApp().saveGameState(""); wxGetApp().saveGameState("");
// Eigener Pfad // Custom path
wxGetApp().saveGameState("/path/to/save.lua"); wxGetApp().saveGameState("/path/to/save.lua");
``` ```
### Spielstand laden ### Load Game State
```cpp ```cpp
// Automatischer Pfad // Automatic path
wxGetApp().loadGameState(""); wxGetApp().loadGameState("");
// Eigener Pfad // Custom path
wxGetApp().loadGameState("/path/to/save.lua"); wxGetApp().loadGameState("/path/to/save.lua");
``` ```
### Im Spiel ### In-Game
- **Menü → Spielstand speichern** (Strg+S) - **Menu → Save Game** (Ctrl+S)
- **MenüSpielstand laden** (Strg+L) - **MenuLoad Game** (Ctrl+L)
## Save-Datei-Format ## Save File Format
Die Save-Datei ist eine lesbare Lua-Datei: The save file is a readable Lua file:
```lua ```lua
-- Wherigo Save State -- Wherigo Save State
@@ -79,51 +79,51 @@ return {
["Visible"] = true, ["Visible"] = true,
["Container"] = <reference to Player> ["Container"] = <reference to Player>
}, },
-- ... weitere Objekte -- ... more objects
} }
``` ```
## Technische Details ## Technical Details
### Serialisierung ### Serialization
Die Implementierung verwendet: The implementation uses:
1. **Rekursives Traversieren** der Lua-Tabellen 1. **Recursive traversal** of Lua tables
2. **Type-Detection** für verschiedene Lua-Typen 2. **Type detection** for different Lua types
3. **Escaping** von Sonderzeichen in Strings 3. **Escaping** of special characters in strings
4. **Referenz-Handling** durch Lua selbst beim Laden 4. **Reference handling** by Lua itself when loading
### Deserialisierung ### Deserialization
1. Save-Datei wird als Lua-Code geladen (`luaL_loadstring`) 1. Save file is loaded as Lua code (`luaL_loadstring`)
2. Ausführung gibt eine Tabelle zurück (`lua_pcall`) 2. Execution returns a table (`lua_pcall`)
3. Tabellen-Einträge werden als Globals wiederhergestellt 3. Table entries are restored as globals
4. UI wird über `notifyStateChanged()` aktualisiert 4. UI is updated via `notifyStateChanged()`
## Performance ## Performance
- **Speichern**: ~10-100ms für typische Cartridges - **Saving**: ~10-100ms for typical cartridges
- **Laden**: ~20-200ms (inkl. Lua-Parsing) - **Loading**: ~20-200ms (including Lua parsing)
- **Dateigröße**: ~10-500KB (abhängig von Cartridge-Komplexität) - **File size**: ~10-500KB (depends on cartridge complexity)
## Erweiterungen ## Extensions
### Eigene Filter ### Custom Filters
```cpp ```cpp
// Nur bestimmte Globals speichern // Save only specific globals
std::vector<std::string> myGlobals = {"Player", "zitemKey", "ztaskMain"}; std::vector<std::string> myGlobals = {"Player", "zitemKey", "ztaskMain"};
wherigo::LuaPersistence::saveGlobals(L, "custom.save", myGlobals); wherigo::LuaPersistence::saveGlobals(L, "custom.save", myGlobals);
``` ```
### Auto-Save beim Beenden ### Auto-Save on Exit
```cpp ```cpp
// In cGame::OnClose() // In cGame::OnClose()
wxGetApp().saveGameState(""); // Auto-Save wxGetApp().saveGameState(""); // Auto-save
``` ```
### Mehrere Save-Slots ### Multiple Save Slots
```cpp ```cpp
std::string slot1 = wxGetApp().getAutoSavePath() + ".slot1"; std::string slot1 = wxGetApp().getAutoSavePath() + ".slot1";
@@ -131,34 +131,34 @@ std::string slot2 = wxGetApp().getAutoSavePath() + ".slot2";
std::string slot3 = wxGetApp().getAutoSavePath() + ".slot3"; std::string slot3 = wxGetApp().getAutoSavePath() + ".slot3";
``` ```
## Bekannte Limitierungen ## Known Limitations
1. **Funktions-Callbacks** werden nicht gespeichert (OnClick, OnEnter, etc.) 1. **Function Callbacks** are not saved (OnClick, OnEnter, etc.)
- Diese bleiben im Cartridge-Code definiert - These remain defined in cartridge code
2. **Zirkuläre Referenzen** werden bei der Rekursion abgebrochen 2. **Circular References** are cut off during recursion
- Max. Tiefe: 10 Ebenen - Max depth: 10 levels
3. **Metatables** gehen verloren 3. **Metatables** are lost
- Nach dem Laden müssen ggf. Metatables neu gesetzt werden - May need to be reset after loading
4. **Timer-Status** wird gespeichert, aber `Remaining` muss ggf. neu berechnet werden 4. **Timer Status** is saved, but `Remaining` may need recalculation
## Debugging ## Debugging
Aktiviere Logging um Save/Load zu tracken: Enable logging to trace save/load:
```cpp ```cpp
wxLogDebug("Saved %zu globals to %s", globals.size(), filePath); wxLogDebug("Saved %zu globals to %s", globals.size(), filePath);
wxLogDebug("Restored %d globals from %s", count, filePath); wxLogDebug("Restored %d globals from %s", count, filePath);
``` ```
## Zukünftige Erweiterungen ## Future Enhancements
Mögliche Verbesserungen: Possible improvements:
- [ ] Kompression der Save-Dateien (zlib) - [ ] Compression of save files (zlib)
- [ ] Verschlüsselung (verhindert Cheating) - [ ] Encryption (prevent cheating)
- [ ] Delta-Saves (nur Änderungen speichern) - [ ] Delta saves (only save changes)
- [ ] Cloud-Sync Integration - [ ] Cloud sync integration
- [ ] Automatisches Backup (3 neueste Saves) - [ ] Automatic backups (keep 3 most recent saves)

View File

@@ -1,32 +1,71 @@
# Wherigo Simulator # Wherigo Player
This project is a desktop application for simulating and running Wherigo geocaches. It allows you to play Wherigo cartridges directly on your computer, making it possible to experience geocaching adventures without a GPS device or mobile app. A desktop application for playing Wherigo geocaching cartridges. Experience geocaching adventures directly on your computer without a GPS device or mobile app.
## Features ## Features
- Load and execute Wherigo cartridges (.gwc files) - **Load and execute Wherigo cartridges** (.gwc files)
- Simulate geocaching locations and actions - **Full game engine** with Lua 5.1.4 interpreter
- Desktop interface for easy navigation and interaction - **Interactive UI** with zones, tasks, inventory, characters, and items
- Support for media and cartridge data - **Media support** - Display images (JPEG, PNG) in dialogs and object details
-**Save/Load game state** - Pause and resume your progress
-**Completion logs** - Generate .gwl files for wherigo.com
-**Event-driven updates** - Real-time UI refresh on game state changes
-**Timer system** - Automatic countdown timers with callbacks
-**Dialog system** - Multi-page dialogs with images and buttons
## Requirements ## Requirements
- C++23 or newer - C++23 or newer
- wxWidgets (for GUI) - wxWidgets 3.3 (for GUI)
- Lua 5.1.4 (for cartridge execution) - Lua 5.1.4 (for cartridge execution)
- CMake 3.20+
## Building
```bash
mkdir build && cd build
cmake ..
cmake --build .
```
## Getting Started ## Getting Started
1. Clone this repository. 1. Download a Wherigo cartridge from [wherigo.com](https://wherigo.com)
2. Build the project using CMake and your preferred compiler. 2. Launch wxWherigo
3. Download a Wherigo cartridge (PocketPC format) from [wherigo.com](https://wherigo.com) 3. Click "Open Cartridge..." and select your .gwc file
4. Open it in the application. 4. Click "Start Game"
5. Use the tabs to interact with zones, tasks, and items
## Keyboard Shortcuts
- **Ctrl+O** - Open cartridge
- **Ctrl+S** - Save game state
- **Ctrl+L** - Load game state
- **Ctrl+E** - Export completion log
## Documentation
- [Lua State Persistence](LUA_PERSISTENCE.md) - Save/Load system
- [Wherigo Completion](WHERIGO_COMPLETION.md) - Completion log format
## Project Structure ## Project Structure
- `main/` - Application entry point and UI ```
- `libs/cartridge/` - Cartridge parsing and media handling wx_wherigo/
- `libs/storage/` - Storage management ├── main/ # Application code
- `libs/lua-5.1.4/` - Lua interpreter │ ├── src/
│ │ ├── ui/ # User interface (cStartScreen, cGameScreen)
│ │ └── lua/ # Lua integration & game engine
│ └── include/
├── components/
│ ├── cartridge/ # .gwc parser
│ ├── storage/ # File handling
│ └── lua-5.1.4/ # Lua interpreter
```
## License ## License
This project is licensed under the MIT License. See `License.md` for details. This project is licensed under the MIT License. See `LICENSE.md` for details.
## Author ## Author
Peter Siegmund (mars3142) Peter Siegmund (mars3142)
## Acknowledgments
- Groundspeak for the Wherigo platform
- wxWidgets team for the GUI framework
- Lua team for the scripting engine

View File

@@ -1,14 +1,14 @@
# Wherigo Completion Log (.gwl) # Wherigo Completion Log (.gwl)
## Übersicht ## Overview
Der Wherigo Player kann jetzt **Completion Logs** im `.gwl`-Format (Wherigo Game Log) generieren, die auf **wherigo.com** hochgeladen werden können, um den Abschluss einer Cartridge nachzuweisen. The Wherigo Player can now generate **Completion Logs** in `.gwl` format (Wherigo Game Log), which can be uploaded to **wherigo.com** to prove completion of a cartridge.
## Format ## Format
Das `.gwl`-Format ist ein XML-Format, das folgende Informationen enthält: The `.gwl` format is an XML format that contains the following information:
### XML-Struktur ### XML Structure
```xml ```xml
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
@@ -69,130 +69,130 @@ Das `.gwl`-Format ist ein XML-Format, das folgende Informationen enthält:
</WherigoGameLog> </WherigoGameLog>
``` ```
## Verwendung ## Usage
### Im Spiel ### In-Game
1. Cartridge spielen und abschließen 1. Play and complete cartridge
2. **Menü → Completion Log exportieren** (Strg+E) 2. **Menu Export Completion Log** (Ctrl+E)
3. Datei speichern (z.B. `TheOmbosIdol_completion.gwl`) 3. Save file (e.g., `Cartridge.gwl`)
4. Auf [wherigo.com](https://www.wherigo.com) hochladen 4. Upload to [wherigo.com](https://www.wherigo.com)
### Im Code ### In Code
```cpp ```cpp
// Completion Log generieren // Generate completion log
wxGetApp().generateCompletionLog(""); // Auto-Path wxGetApp().generateCompletionLog(""); // Auto-Path
// Mit eigenem Pfad // With custom path
wxGetApp().generateCompletionLog("/path/to/completion.gwl"); wxGetApp().generateCompletionLog("/path/to/completion.gwl");
// Pfad abrufen // Get path
std::string path = wxGetApp().getCompletionLogPath(); std::string path = wxGetApp().getCompletionLogPath();
``` ```
## Was wird erfasst? ## What is Captured?
### ✅ Cartridge-Informationen ### ✅ Cartridge Information
- Name der Cartridge - Cartridge name
- GUID (eindeutige ID) - GUID (unique ID)
### ✅ Spieler-Informationen ### ✅ Player Information
- Spielername (Standard: "Player") - Player name (default: "Player")
### ✅ Session-Daten ### ✅ Session Data
- Startzeit (aktuell: Zeitpunkt der Generierung) - Start time (currently: generation timestamp)
- Endzeit (aktuell: Zeitpunkt der Generierung) - End time (currently: generation timestamp)
- Gesamtdauer in Sekunden - Total duration in seconds
### ✅ Completion Status ### ✅ Completion Status
- `Complete` - Alle Tasks abgeschlossen - `Complete` - All tasks completed
- `Incomplete` - Noch offene Tasks - `Incomplete` - Tasks still pending
### ✅ Aufgaben (Tasks) ### ✅ Tasks
- Name der Aufgabe - Task name
- Status (completed: true/false) - Status (completed: true/false)
- Abschlusszeit (falls completed) - Completion time (if completed)
### ✅ Gesammelte Items ### ✅ Collected Items
- Name des Items - Item name
- Zeitpunkt des Einsammelns - Collection timestamp
- **Nur Items im Spieler-Inventar** - **Only items in player inventory**
### ✅ Besuchte Zonen ### ✅ Visited Zones
- Name der Zone - Zone name
- Zeitpunkt des Besuchs - Visit timestamp
- **Nur aktive Zonen** - **Only active zones**
### ✅ Completion Code ### ✅ Completion Code
- Eindeutiger Hash/Signatur-Code - Unique hash/signature code
- Basiert auf: Cartridge-GUID + Spielername + Abschlusszeit - Based on: Cartridge GUID + Player name + Completion time
- Format: 16-stelliger Hex-Code (z.B. `A1B2C3D4E5F67890`) - Format: 16-digit hex code (e.g., `A1B2C3D4E5F67890`)
## Technische Details ## Technical Details
### Dateipfad ### File Path
Standardpfad für Completion Logs: Default path for completion logs:
- **Im gleichen Verzeichnis wie die GWC-Datei** - **In the same directory as the GWC file**
- Format: `<GWC-Verzeichnis>/<CartridgeName>.gwl` - Format: `<GWC-Directory>/<CartridgeName>.gwl`
Beispiel: Example:
- GWC-Datei: `/Users/name/Downloads/TheOmbosIdol.gwc` - GWC file: `/Users/<name>/Downloads/<CartridgeName>.gwc`
- Completion Log: `/Users/name/Downloads/TheOmbosIdol.gwl` - Completion log: `/Users/<name>/Downloads/<CartridgeName>.gwl`
Dies ermöglicht es, die Completion-Logs zusammen mit den Cartridge-Dateien zu organisieren. This allows organizing completion logs together with cartridge files.
### XML-Encoding ### XML Encoding
- UTF-8 - UTF-8
- Sonderzeichen werden escaped: `&`, `<`, `>`, `"`, `'` - Special characters are escaped: `&`, `<`, `>`, `"`, `'`
### Zeitformat ### Time Format
- ISO 8601: `YYYY-MM-DDTHH:MM:SS` - ISO 8601: `YYYY-MM-DDTHH:MM:SS`
- Beispiel: `2026-02-13T16:45:00` - Example: `2026-02-13T16:45:00`
- Lokale Zeitzone - Local timezone
### Completion Code Generierung ### Completion Code Generation
```cpp ```cpp
// Einfacher Hash-Algorithmus (für Produktion: SHA256 verwenden) // Simple hash algorithm (use SHA256 for production)
hash = hash_function(cartridgeGUID + playerName + endTime) hash = hash_function(cartridgeGUID + playerName + endTime)
completionCode = sprintf("%016lX", hash) completionCode = sprintf("%016lX", hash)
``` ```
## Limitierungen ## Limitations
### ⚠️ Session-Zeiten ### ⚠️ Session Times
Die aktuellen Start-/Endzeiten sind der **Zeitpunkt der Generierung**, nicht die tatsächliche Spielzeit. Um echte Session-Tracking zu implementieren: Current start/end times are the **generation timestamp**, not actual playtime. To implement real session tracking:
```cpp ```cpp
// In cApp beim Start speichern: // Save in cApp at start:
m_sessionStartTime = time(nullptr); m_sessionStartTime = time(nullptr);
// Bei Completion verwenden: // Use at completion:
data.startTime = m_sessionStartTime; data.startTime = m_sessionStartTime;
data.endTime = time(nullptr); data.endTime = time(nullptr);
data.duration = data.endTime - data.startTime; data.duration = data.endTime - data.startTime;
``` ```
### ⚠️ Completion Code ### ⚠️ Completion Code
Der aktuelle Hash-Algorithmus ist simpel. Für echte Verifikation sollte **SHA256** oder ein ähnlicher kryptografischer Hash verwendet werden. The current hash algorithm is simple. For real verification, **SHA256** or similar cryptographic hash should be used.
### ⚠️ Wherigo.com Upload ### ⚠️ Wherigo.com Upload
Das generierte Format entspricht dem Wherigo-Standard, aber die tatsächliche Akzeptanz auf wherigo.com hängt von deren Server-seitiger Validierung ab. The generated format follows the Wherigo standard, but actual acceptance on wherigo.com depends on their server-side validation.
## Erweiterungen ## Extensions
### Spielername anpassen ### Customize Player Name
```cpp ```cpp
// In cApp/cGame speichern: // Store in cApp/cGameScreen:
std::string m_playerName = "Player"; std::string m_playerName = "Player";
// Beim Generieren verwenden: // Use when generating:
wherigo::WherigoCompletion::generateCompletionLog(L, path, m_playerName); wherigo::WherigoCompletion::generateCompletionLog(L, path, m_playerName);
``` ```
### Session-Tracking ### Session Tracking
```cpp ```cpp
class cApp { class cApp {
time_t m_sessionStartTime = 0; time_t m_sessionStartTime = 0;
@@ -204,51 +204,51 @@ class cApp {
}; };
``` ```
### Zusätzliche Statistiken ### Additional Statistics
Das `CompletionData`-Struct kann erweitert werden um: The `CompletionData` struct can be extended with:
- Anzahl der Dialoge - Number of dialogs
- Zurückgelegte Distanz - Distance traveled
- Verwendete Hints - Hints used
- Fehlversuche - Failed attempts
### Auto-Export bei Abschluss ### Auto-Export on Completion
```cpp ```cpp
// In cGame::OnTaskCompleted() oder bei Complete-Event // In cGameScreen::OnTaskCompleted() or on Complete event
if (allTasksCompleted()) { if (allTasksCompleted()) {
wxGetApp().generateCompletionLog(""); wxGetApp().generateCompletionLog("");
wxMessageBox("Gratulation! Completion Log wurde automatisch erstellt."); wxMessageBox("Congratulations! Completion log automatically created.");
} }
``` ```
## Beispiel-Workflow ## Example Workflow
1. **Spieler spielt Cartridge** 1. **Player plays cartridge**
2. **Alle Tasks werden abgeschlossen** 2. **All tasks completed**
3. **Spieler exportiert Log:** Menü → Completion Log exportieren 3. **Player exports log:** Menu Export Completion Log
4. **Datei wird gespeichert:** `TheOmbosIdol_completion.gwl` 4. **File saved:** `<CartridgeName>.gwl`
5. **Upload auf wherigo.com:** 5. **Upload to wherigo.com:**
- Login auf wherigo.com - Login to wherigo.com
- Zur Cartridge-Seite navigieren - Navigate to cartridge page
- "Log completed cartridge" Button - Click "Log completed cartridge"
- `.gwl`-Datei hochladen - Upload `.gwl` file
- Completion wird verifiziert und angezeigt - Completion verified and displayed
## Debugging ## Debugging
Log-Ausgaben aktivieren: Enable log output:
```cpp ```cpp
wxLogMessage("Completion log generated: %s", filePath); wxLogMessage("Completion log generated: %s", filePath);
wxLogDebug("Tasks completed: %d/%d", completedCount, totalCount); wxLogDebug("Tasks completed: %d/%d", completedCount, totalCount);
``` ```
## Zukünftige Features ## Future Features
- [ ] Automatisches Tracking der Session-Zeit - [ ] Automatic session time tracking
- [ ] Spielername-Eingabe-Dialog - [ ] Player name input dialog
- [ ] Screenshot/Foto-Anhänge - [ ] Screenshot/photo attachments
- [ ] GPS-Koordinaten für besuchte Zonen - [ ] GPS coordinates for visited zones
- [ ] Statistiken (Distanz, Zeit pro Zone, etc.) - [ ] Statistics (distance, time per zone, etc.)
- [ ] Automatischer Export bei Completion - [ ] Automatic export on completion
- [ ] Cloud-Upload direkt aus der App - [ ] Cloud upload directly from app
- [ ] Kryptografischer Completion Code (SHA256) - [ ] Cryptographic completion code (SHA256)