feat: cross acount / cross realm character data

This commit is contained in:
Vati
2026-04-06 16:24:39 +04:00
parent daca27ca5c
commit 4d60e4fd53
6 changed files with 2781 additions and 2535 deletions
+81 -8
View File
@@ -314,6 +314,8 @@ end
-- Get all characters (optionally filter by faction and/or realm)
function DB:GetAllCharacters(sameFactionOnly, currentRealmOnly)
local chars = {}
-- Own characters from SavedVariables
for fullName, data in pairs(Guda_DB.characters) do
local factionMatch = not sameFactionOnly or data.faction == playerFaction
local realmMatch = not currentRealmOnly or data.realm == playerRealm
@@ -323,17 +325,38 @@ function DB:GetAllCharacters(sameFactionOnly, currentRealmOnly)
name = data.name,
realm = data.realm,
class = data.class,
classToken = data.classToken, -- English uppercase token for colors
classToken = data.classToken,
level = data.level,
faction = data.faction,
money = data.money,
lastUpdate = data.lastUpdate,
account = data.account,
isShared = data.isShared,
})
end
end
-- Shared characters from other accounts (in-memory only)
if addon.sharedCharacters then
for fullName, data in pairs(addon.sharedCharacters) do
local factionMatch = not sameFactionOnly or data.faction == playerFaction
local realmMatch = not currentRealmOnly or data.realm == playerRealm
if factionMatch and realmMatch then
table.insert(chars, {
fullName = fullName,
name = data.name,
realm = data.realm,
class = data.class,
classToken = data.classToken,
level = data.level,
faction = data.faction,
money = data.money,
lastUpdate = data.lastUpdate,
account = data.account,
isShared = true,
})
end
end
end
-- Sort by name
table.sort(chars, function(a, b)
return a.name < b.name
@@ -342,21 +365,30 @@ function DB:GetAllCharacters(sameFactionOnly, currentRealmOnly)
return chars
end
-- Look up a character in own DB or shared characters
function DB:GetCharacterData(fullName)
local char = Guda_DB.characters[fullName]
if not char and addon.sharedCharacters then
char = addon.sharedCharacters[fullName]
end
return char
end
-- Get character's bags
function DB:GetCharacterBags(fullName)
local char = Guda_DB.characters[fullName]
local char = self:GetCharacterData(fullName)
return char and char.bags or {}
end
-- Get character's bank
function DB:GetCharacterBank(fullName)
local char = Guda_DB.characters[fullName]
local char = self:GetCharacterData(fullName)
return char and char.bank or {}
end
-- Get character's mailbox
function DB:GetCharacterMailbox(fullName)
local char = Guda_DB.characters[fullName]
local char = self:GetCharacterData(fullName)
return char and char.mailbox or {}
end
@@ -415,13 +447,13 @@ end
-- Get character's equipped items
function DB:GetCharacterEquipped(fullName)
local char = Guda_DB.characters[fullName]
local char = self:GetCharacterData(fullName)
return char and char.equipped or {}
end
-- Get character info
function DB:GetCharacterInfo(fullName)
local char = Guda_DB.characters[fullName]
local char = self:GetCharacterData(fullName)
return char and char.character or {}
end
@@ -435,6 +467,16 @@ function DB:GetTotalMoney(sameFactionOnly, currentRealmOnly)
total = total + (data.money or 0)
end
end
-- Include shared characters
if addon.sharedCharacters then
for fullName, data in pairs(addon.sharedCharacters) do
local factionMatch = not sameFactionOnly or data.faction == playerFaction
local realmMatch = not currentRealmOnly or data.realm == playerRealm
if factionMatch and realmMatch then
total = total + (data.money or 0)
end
end
end
return total
end
@@ -455,6 +497,37 @@ function DB:ToggleGoldBlacklist(fullName)
end
end
-- Clean up blacklist entries for characters that no longer exist
-- Call after SharedData import so shared characters are present
function DB:CleanupBlacklist()
if not Guda_DB.goldBlacklist then return end
for fullName in pairs(Guda_DB.goldBlacklist) do
local exists = Guda_DB.characters[fullName] or (addon.sharedCharacters and addon.sharedCharacters[fullName])
if not exists then
Guda_DB.goldBlacklist[fullName] = nil
end
end
end
-- Remove a character from the database entirely
function DB:RemoveCharacter(fullName)
if not fullName then return end
-- Don't allow removing the current character
local currentFullName = playerName and playerRealm and (playerName .. "-" .. playerRealm)
if fullName == currentFullName then return false end
if Guda_DB.characters[fullName] then
Guda_DB.characters[fullName] = nil
end
if addon.sharedCharacters and addon.sharedCharacters[fullName] then
addon.sharedCharacters[fullName] = nil
end
if Guda_DB.goldBlacklist and Guda_DB.goldBlacklist[fullName] then
Guda_DB.goldBlacklist[fullName] = nil
end
return true
end
-- Get character setting
function DB:GetSetting(key)
-- SavedVariables may not be initialized yet when some UI OnLoad scripts run
+3
View File
@@ -20,6 +20,9 @@ function Main:Initialize()
addon.Modules.SharedData:Initialize()
end
-- Clean up blacklist for deleted characters (after shared import)
addon.Modules.DB:CleanupBlacklist()
-- Initialize item detection (before scanners, as they may use it)
if addon.Modules.ItemDetection then
addon.Modules.ItemDetection:Initialize()
+25 -12
View File
@@ -2,33 +2,47 @@
-- Cross-account character data sharing via GudaIO DLL (optional)
-- The DLL merges all accounts' SavedVariables at startup into GudaShared.lua
-- which is loaded via .toc and sets Guda_SharedCharacters global.
-- No Lua hooking needed - pure file I/O at DLL load time.
--
-- IMPORTANT: Shared characters are stored in addon.sharedCharacters (in-memory only),
-- NOT in Guda_DB.characters, to prevent them from leaking into SavedVariables.
local addon = Guda
local SharedData = {}
addon.Modules.SharedData = SharedData
-- Import shared characters from other accounts
function SharedData:Initialize()
-- Clean up any leaked shared characters from the old approach
if Guda_DB and Guda_DB.characters then
for fullName, data in pairs(Guda_DB.characters) do
if data.isShared then
Guda_DB.characters[fullName] = nil
else
-- Strip leaked fields from own characters
data.isShared = nil
data.account = nil
end
end
end
-- Initialize in-memory shared characters table
addon.sharedCharacters = {}
if not Guda_SharedCharacters or type(Guda_SharedCharacters) ~= "table" then
return
end
-- Determine current account by checking which characters are ours
-- (characters in Guda_DB.characters that don't have isShared flag)
-- Determine which characters belong to the current account
local myChars = {}
if Guda_DB and Guda_DB.characters then
for fullName, data in pairs(Guda_DB.characters) do
if not data.isShared then
myChars[fullName] = true
end
for fullName in pairs(Guda_DB.characters) do
myChars[fullName] = true
end
end
-- Find which account name belongs to us by checking overlap
local myAccount = nil
local accountChars = {} -- account -> { fullName -> true }
local accountChars = {}
for fullName, charData in pairs(Guda_SharedCharacters) do
local acct = charData.account
if acct then
@@ -47,13 +61,12 @@ function SharedData:Initialize()
if myAccount then break end
end
-- Import characters from other accounts
-- Import characters from other accounts into in-memory table
local importCount = 0
for fullName, charData in pairs(Guda_SharedCharacters) do
if charData.account and charData.account ~= myAccount then
-- Don't overwrite our own characters
if not myChars[fullName] then
Guda_DB.characters[fullName] = {
addon.sharedCharacters[fullName] = {
name = charData.name,
realm = charData.realm,
faction = charData.faction,
+29 -26
View File
@@ -277,36 +277,39 @@ function Tooltip:AddInventoryInfo(tooltip, link)
local currentPlayerName = addon.Modules.DB:GetPlayerFullName()
local currentRealm = GetRealmName()
-- Count items across characters on current realm only
for charName, charData in pairs(Guda_DB.characters) do
-- Ensure charData is actually a table, on current realm, and not blacklisted
if type(charData) == "table" and charData.realm == currentRealm and not addon.Modules.DB:IsGoldBlacklisted(charName) then
local isCurrentChar = (charName == currentPlayerName)
local bagCount, bankCount, equippedCount, mailCount = CountItemsForCharacter(itemID, charData, isCurrentChar)
-- Count items across characters on current realm only (own + shared)
local function countFromSource(source, isSharedSource)
for charName, charData in pairs(source) do
if type(charData) == "table" and charData.realm == currentRealm and not addon.Modules.DB:IsGoldBlacklisted(charName) then
local isCurrentChar = (charName == currentPlayerName)
local bagCount, bankCount, equippedCount, mailCount = CountItemsForCharacter(itemID, charData, isCurrentChar)
if bagCount > 0 or bankCount > 0 or equippedCount > 0 or mailCount > 0 then
hasAnyItems = true
totalBags = totalBags + bagCount
totalBank = totalBank + bankCount
totalMail = totalMail + mailCount
totalEquipped = totalEquipped + equippedCount
ccIndex = ccIndex + 1
-- Reuse existing sub-table or create one that persists
if not characterCounts[ccIndex] then
characterCounts[ccIndex] = {}
if bagCount > 0 or bankCount > 0 or equippedCount > 0 or mailCount > 0 then
hasAnyItems = true
totalBags = totalBags + bagCount
totalBank = totalBank + bankCount
totalMail = totalMail + mailCount
totalEquipped = totalEquipped + equippedCount
ccIndex = ccIndex + 1
if not characterCounts[ccIndex] then
characterCounts[ccIndex] = {}
end
local entry = characterCounts[ccIndex]
entry.name = charData.name or charName
entry.classToken = charData.classToken
entry.bagCount = bagCount
entry.bankCount = bankCount
entry.mailCount = mailCount
entry.equippedCount = equippedCount
entry.isCurrent = isCurrentChar
entry.isShared = isSharedSource
end
local entry = characterCounts[ccIndex]
entry.name = charData.name or charName
entry.classToken = charData.classToken
entry.bagCount = bagCount
entry.bankCount = bankCount
entry.mailCount = mailCount
entry.equippedCount = equippedCount
entry.isCurrent = isCurrentChar
entry.isShared = charData.isShared
end
end
-- If charData is not a table (string, number, etc.), just skip it
end
countFromSource(Guda_DB.characters, false)
if addon.sharedCharacters then
countFromSource(addon.sharedCharacters, true)
end
-- Clean up any stale entries beyond current count
for i = ccIndex + 1, table.getn(characterCounts) do