feat: add SavedVariables persistence for Lua addons

Addons can now persist data across sessions using the standard WoW
SavedVariables pattern:

1. Declare in .toc: ## SavedVariables: MyAddonDB
2. Use the global in Lua: MyAddonDB = MyAddonDB or {default = true}
3. Data is automatically saved on logout and restored on next login

Implementation:
- TocFile::getSavedVariables() parses comma-separated variable names
- LuaEngine::loadSavedVariables() executes saved .lua file to restore globals
- LuaEngine::saveSavedVariables() serializes Lua tables/values to valid Lua
- Serializer handles tables (nested), strings, numbers, booleans, nil
- Save triggered on PLAYER_LEAVING_WORLD and AddonManager::shutdown()
- Files stored as <AddonDir>/<AddonName>.lua.saved

Updated HelloWorld addon to track login count across sessions.
This commit is contained in:
Kelsi 2026-03-20 12:22:50 -07:00
parent 5ea5588c14
commit 062cfd1e4a
9 changed files with 177 additions and 2 deletions

View file

@ -61,10 +61,21 @@ void AddonManager::loadAllAddons() {
(failed > 0 ? (", " + std::to_string(failed) + " failed") : ""));
}
std::string AddonManager::getSavedVariablesPath(const TocFile& addon) const {
return addon.basePath + "/" + addon.addonName + ".lua.saved";
}
bool AddonManager::loadAddon(const TocFile& addon) {
// Load SavedVariables before addon code (so globals are available at load time)
auto savedVars = addon.getSavedVariables();
if (!savedVars.empty()) {
std::string svPath = getSavedVariablesPath(addon);
luaEngine_.loadSavedVariables(svPath);
LOG_DEBUG("AddonManager: loaded saved variables for '", addon.addonName, "'");
}
bool success = true;
for (const auto& filename : addon.files) {
// For Step 1: only load .lua files, skip .xml (frame system not yet implemented)
std::string lower = filename;
for (char& c : lower) c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
@ -93,7 +104,18 @@ void AddonManager::update(float deltaTime) {
luaEngine_.dispatchOnUpdate(deltaTime);
}
void AddonManager::saveAllSavedVariables() {
for (const auto& addon : addons_) {
auto savedVars = addon.getSavedVariables();
if (!savedVars.empty()) {
std::string svPath = getSavedVariablesPath(addon);
luaEngine_.saveSavedVariables(svPath, savedVars);
}
}
}
void AddonManager::shutdown() {
saveAllSavedVariables();
addons_.clear();
luaEngine_.shutdown();
}