# Lua State Persistence / Save Game System

## Overview

The Wherigo Player can save and restore the Lua state to preserve game progress.

## How It Works

### Automatic Save Locations

Game saves are automatically stored at:
- **macOS**: `~/Library/Application Support/wxWherigo/<CartridgeName>.save`
- **Windows**: `%APPDATA%\wxWherigo\<CartridgeName>.save`
- **Linux**: `~/.wxWherigo/<CartridgeName>.save`

### What is Saved?

Persistence saves:
- ✅ **All Wherigo Objects**: ZCartridge, Zone, ZItem, ZCharacter, ZTask, ZTimer, ZInput, ZMedia
- ✅ **Object Properties**: Name, Description, Active, Visible, Container, etc.
- ✅ **Global Variables**: All simple variables (Strings, Numbers, Booleans)
- ✅ **Player Object**: Position, inventory, etc.
- ✅ **Nested Tables**: Recursive serialization (up to depth 10)

### What is NOT Saved?

- ❌ **Functions**: Lua functions cannot be serialized
- ❌ **Userdata**: C objects remain in original state
- ❌ **Threads/Coroutines**: Saved as `nil`
- ❌ **Metatables**: Not persisted

## Usage in Code

### Save Game State

```cpp
// Automatic path (recommended)
wxGetApp().saveGameState("");

// Custom path
wxGetApp().saveGameState("/path/to/save.lua");
```

### Load Game State

```cpp
// Automatic path
wxGetApp().loadGameState("");

// Custom path
wxGetApp().loadGameState("/path/to/save.lua");
```

### In-Game

- **Menu → Save Game** (Ctrl+S)
- **Menu → Load Game** (Ctrl+L)

## Save File Format

The save file is a readable Lua file:

```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"] = <reference to Player>
  },
  -- ... more objects
}
```

## Technical Details

### Serialization

The implementation uses:
1. **Recursive traversal** of Lua tables
2. **Type detection** for different Lua types
3. **Escaping** of special characters in strings
4. **Reference handling** by Lua itself when loading

### Deserialization

1. Save file is loaded as Lua code (`luaL_loadstring`)
2. Execution returns a table (`lua_pcall`)
3. Table entries are restored as globals
4. UI is updated via `notifyStateChanged()`

## Performance

- **Saving**: ~10-100ms for typical cartridges
- **Loading**: ~20-200ms (including Lua parsing)
- **File size**: ~10-500KB (depends on cartridge complexity)

## Extensions

### Custom Filters

```cpp
// Save only specific globals
std::vector<std::string> myGlobals = {"Player", "zitemKey", "ztaskMain"};
wherigo::LuaPersistence::saveGlobals(L, "custom.save", myGlobals);
```

### Auto-Save on Exit

```cpp
// In cGame::OnClose()
wxGetApp().saveGameState("");  // Auto-save
```

### Multiple Save Slots

```cpp
std::string slot1 = wxGetApp().getAutoSavePath() + ".slot1";
std::string slot2 = wxGetApp().getAutoSavePath() + ".slot2";
std::string slot3 = wxGetApp().getAutoSavePath() + ".slot3";
```

## Known Limitations

1. **Function Callbacks** are not saved (OnClick, OnEnter, etc.)
   - These remain defined in cartridge code
   
2. **Circular References** are cut off during recursion
   - Max depth: 10 levels

3. **Metatables** are lost
   - May need to be reset after loading

4. **Timer Status** is saved, but `Remaining` may need recalculation

## Debugging

Enable logging to trace save/load:

```cpp
wxLogDebug("Saved %zu globals to %s", globals.size(), filePath);
wxLogDebug("Restored %d globals from %s", count, filePath);
```

## Future Enhancements

Possible improvements:
- [ ] Compression of save files (zlib)
- [ ] Encryption (prevent cheating)
- [ ] Delta saves (only save changes)
- [ ] Cloud sync integration
- [ ] Automatic backups (keep 3 most recent saves)

