mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
feat: support SavedVariablesPerCharacter for per-character addon data
Implement the SavedVariablesPerCharacter TOC directive that many addons use to store different settings per character (Bartender, Dominos, MoveAnything, WeakAuras, etc.). Without this, all characters share the same addon data file. Per-character files are stored as <AddonName>.<CharacterName>.lua.saved alongside the existing account-wide <AddonName>.lua.saved files. The character name is resolved from the player GUID at world entry time. Changes: - TocFile::getSavedVariablesPerCharacter() parses the TOC directive - AddonManager loads/saves per-character vars alongside account-wide vars - Character name set from game handler before addon loading
This commit is contained in:
parent
0d2fd02dca
commit
e21f808714
5 changed files with 51 additions and 6 deletions
|
|
@ -26,6 +26,7 @@ public:
|
||||||
bool isInitialized() const { return luaEngine_.isInitialized(); }
|
bool isInitialized() const { return luaEngine_.isInitialized(); }
|
||||||
|
|
||||||
void saveAllSavedVariables();
|
void saveAllSavedVariables();
|
||||||
|
void setCharacterName(const std::string& name) { characterName_ = name; }
|
||||||
|
|
||||||
/// Re-initialize the Lua VM and reload all addons (used by /reload).
|
/// Re-initialize the Lua VM and reload all addons (used by /reload).
|
||||||
bool reload();
|
bool reload();
|
||||||
|
|
@ -38,6 +39,8 @@ private:
|
||||||
|
|
||||||
bool loadAddon(const TocFile& addon);
|
bool loadAddon(const TocFile& addon);
|
||||||
std::string getSavedVariablesPath(const TocFile& addon) const;
|
std::string getSavedVariablesPath(const TocFile& addon) const;
|
||||||
|
std::string getSavedVariablesPerCharacterPath(const TocFile& addon) const;
|
||||||
|
std::string characterName_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace wowee::addons
|
} // namespace wowee::addons
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ struct TocFile {
|
||||||
std::string getInterface() const;
|
std::string getInterface() const;
|
||||||
bool isLoadOnDemand() const;
|
bool isLoadOnDemand() const;
|
||||||
std::vector<std::string> getSavedVariables() const;
|
std::vector<std::string> getSavedVariables() const;
|
||||||
|
std::vector<std::string> getSavedVariablesPerCharacter() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<TocFile> parseTocFile(const std::string& tocPath);
|
std::optional<TocFile> parseTocFile(const std::string& tocPath);
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,11 @@ std::string AddonManager::getSavedVariablesPath(const TocFile& addon) const {
|
||||||
return addon.basePath + "/" + addon.addonName + ".lua.saved";
|
return addon.basePath + "/" + addon.addonName + ".lua.saved";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string AddonManager::getSavedVariablesPerCharacterPath(const TocFile& addon) const {
|
||||||
|
if (characterName_.empty()) return "";
|
||||||
|
return addon.basePath + "/" + addon.addonName + "." + characterName_ + ".lua.saved";
|
||||||
|
}
|
||||||
|
|
||||||
bool AddonManager::loadAddon(const TocFile& addon) {
|
bool AddonManager::loadAddon(const TocFile& addon) {
|
||||||
// Load SavedVariables before addon code (so globals are available at load time)
|
// Load SavedVariables before addon code (so globals are available at load time)
|
||||||
auto savedVars = addon.getSavedVariables();
|
auto savedVars = addon.getSavedVariables();
|
||||||
|
|
@ -76,6 +81,15 @@ bool AddonManager::loadAddon(const TocFile& addon) {
|
||||||
luaEngine_.loadSavedVariables(svPath);
|
luaEngine_.loadSavedVariables(svPath);
|
||||||
LOG_DEBUG("AddonManager: loaded saved variables for '", addon.addonName, "'");
|
LOG_DEBUG("AddonManager: loaded saved variables for '", addon.addonName, "'");
|
||||||
}
|
}
|
||||||
|
// Load per-character SavedVariables
|
||||||
|
auto savedVarsPC = addon.getSavedVariablesPerCharacter();
|
||||||
|
if (!savedVarsPC.empty()) {
|
||||||
|
std::string svpcPath = getSavedVariablesPerCharacterPath(addon);
|
||||||
|
if (!svpcPath.empty()) {
|
||||||
|
luaEngine_.loadSavedVariables(svpcPath);
|
||||||
|
LOG_DEBUG("AddonManager: loaded per-character saved variables for '", addon.addonName, "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
for (const auto& filename : addon.files) {
|
for (const auto& filename : addon.files) {
|
||||||
|
|
@ -120,6 +134,13 @@ void AddonManager::saveAllSavedVariables() {
|
||||||
std::string svPath = getSavedVariablesPath(addon);
|
std::string svPath = getSavedVariablesPath(addon);
|
||||||
luaEngine_.saveSavedVariables(svPath, savedVars);
|
luaEngine_.saveSavedVariables(svPath, savedVars);
|
||||||
}
|
}
|
||||||
|
auto savedVarsPC = addon.getSavedVariablesPerCharacter();
|
||||||
|
if (!savedVarsPC.empty()) {
|
||||||
|
std::string svpcPath = getSavedVariablesPerCharacterPath(addon);
|
||||||
|
if (!svpcPath.empty()) {
|
||||||
|
luaEngine_.saveSavedVariables(svpcPath, savedVarsPC);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,17 +19,12 @@ bool TocFile::isLoadOnDemand() const {
|
||||||
return (it != directives.end()) && it->second == "1";
|
return (it != directives.end()) && it->second == "1";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> TocFile::getSavedVariables() const {
|
static std::vector<std::string> parseVarList(const std::string& val) {
|
||||||
std::vector<std::string> result;
|
std::vector<std::string> result;
|
||||||
auto it = directives.find("SavedVariables");
|
|
||||||
if (it == directives.end()) return result;
|
|
||||||
// Parse comma-separated variable names
|
|
||||||
std::string val = it->second;
|
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
while (pos <= val.size()) {
|
while (pos <= val.size()) {
|
||||||
size_t comma = val.find(',', pos);
|
size_t comma = val.find(',', pos);
|
||||||
std::string name = (comma != std::string::npos) ? val.substr(pos, comma - pos) : val.substr(pos);
|
std::string name = (comma != std::string::npos) ? val.substr(pos, comma - pos) : val.substr(pos);
|
||||||
// Trim whitespace
|
|
||||||
size_t start = name.find_first_not_of(" \t");
|
size_t start = name.find_first_not_of(" \t");
|
||||||
size_t end = name.find_last_not_of(" \t");
|
size_t end = name.find_last_not_of(" \t");
|
||||||
if (start != std::string::npos)
|
if (start != std::string::npos)
|
||||||
|
|
@ -40,6 +35,16 @@ std::vector<std::string> TocFile::getSavedVariables() const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> TocFile::getSavedVariables() const {
|
||||||
|
auto it = directives.find("SavedVariables");
|
||||||
|
return (it != directives.end()) ? parseVarList(it->second) : std::vector<std::string>{};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> TocFile::getSavedVariablesPerCharacter() const {
|
||||||
|
auto it = directives.find("SavedVariablesPerCharacter");
|
||||||
|
return (it != directives.end()) ? parseVarList(it->second) : std::vector<std::string>{};
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<TocFile> parseTocFile(const std::string& tocPath) {
|
std::optional<TocFile> parseTocFile(const std::string& tocPath) {
|
||||||
std::ifstream f(tocPath);
|
std::ifstream f(tocPath);
|
||||||
if (!f.is_open()) return std::nullopt;
|
if (!f.is_open()) return std::nullopt;
|
||||||
|
|
|
||||||
|
|
@ -5182,6 +5182,21 @@ void Application::loadOnlineWorldTerrain(uint32_t mapId, float x, float y, float
|
||||||
|
|
||||||
// Load addons once per session on first world entry
|
// Load addons once per session on first world entry
|
||||||
if (addonManager_ && !addonsLoaded_) {
|
if (addonManager_ && !addonsLoaded_) {
|
||||||
|
// Set character name for per-character SavedVariables
|
||||||
|
if (gameHandler) {
|
||||||
|
const std::string& charName = gameHandler->lookupName(gameHandler->getPlayerGuid());
|
||||||
|
if (!charName.empty()) {
|
||||||
|
addonManager_->setCharacterName(charName);
|
||||||
|
} else {
|
||||||
|
// Fallback: find name from character list
|
||||||
|
for (const auto& c : gameHandler->getCharacters()) {
|
||||||
|
if (c.guid == gameHandler->getPlayerGuid()) {
|
||||||
|
addonManager_->setCharacterName(c.name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
addonManager_->loadAllAddons();
|
addonManager_->loadAllAddons();
|
||||||
addonsLoaded_ = true;
|
addonsLoaded_ = true;
|
||||||
addonManager_->fireEvent("VARIABLES_LOADED");
|
addonManager_->fireEvent("VARIABLES_LOADED");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue