--[[ Name: AceDB-2.0 Revision: $Rev: 4763 $ Author(s): ckknight (ckknight@gmail.com) Inspired By: AceDB 1.x by Turan () Website: http://www.wowace.com/ Documentation: http://wiki.wowace.com/index.php/AceDB-2.0 SVN: http://svn.wowace.com/root/trunk/Ace2/AceDB-2.0 Description: Mixin to allow for fast, clean, and featureful saved variable access. Dependencies: AceLibrary, AceOO-2.0, AceEvent-2.0 ]] local MAJOR_VERSION = "AceDB-2.0" local MINOR_VERSION = "$Revision: 4763 $" if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end -- localize -- local ACTIVE = "Active" local STATE = "State" local TOGGLE_ACTIVE = "Suspend/resume this addon" local MAP_ACTIVESUSPENDED = { [true] = "|cff00ff00Active|r", [false] = "|cffff0000Suspended|r" } local SET_PROFILE = "Set profile for this addon" local SET_PROFILE_USAGE = "{char || class || realm || }" local PROFILE = "Profile" local PLAYER_OF_REALM = "%s of %s" -- localize -- local AceOO = AceLibrary("AceOO-2.0") local AceEvent local Mixin = AceOO.Mixin local AceDB = Mixin { "RegisterDB", "RegisterDefaults", "ResetDB", "SetProfile", "GetProfile", "ToggleActive", "IsActive", "AcquireDBNamespace", "ToggleStandby", -- remove at 2006-07-21 "IsEnabled", -- remove at 2006-07-21 } local _G = getfenv(0) local function inheritDefaults(t, defaults) if not defaults then return t end for k,v in pairs(defaults) do if k == "*" then local v = v if type(v) == "table" then setmetatable(t, { __index = function(self, key) if key == nil then return nil end self[key] = {} inheritDefaults(self[key], v) return self[key] end } ) else setmetatable(t, { __index = function(self, key) if key == nil then return nil end self[key] = v return self[key] end } ) end for key in pairs(t) do if (defaults[key] == nil or key == "*") and type(t[key]) == "table" then inheritDefaults(t[key], v) end end else if type(v) == "table" then if type(t[k]) ~= "table" then t[k] = {} end inheritDefaults(t[k], v) elseif t[k] == nil then t[k] = v end end end return t end local _,race = UnitRace("player") local faction if race == "Orc" or race == "Scourge" or race == "Troll" or race == "Tauren" then faction = FACTION_HORDE else faction = FACTION_ALLIANCE end local charID = string.format(PLAYER_OF_REALM, UnitName("player"), (string.gsub(GetRealmName(), "^%s*(.-)%s*$", "%1"))) local realm = string.gsub(GetRealmName(), "^%s*(.-)%s*$", "%1") local realmID = realm .. " - " .. faction local classID = UnitClass("player") AceDB.CHAR_ID = charID AceDB.REALM_ID = realmID AceDB.CLASS_ID = classID AceDB.FACTION = faction AceDB.REALM = realm AceDB.NAME = UnitName("player") local caseInsensitive_mt = { __index = function(self, key) if type(key) ~= "string" then return nil end local lowerKey = string.lower(key) for k,v in pairs(self) do if string.lower(k) == lowerKey then return self[k] end end end, __newindex = function(self, key, value) if type(key) ~= "string" then return error("table index is nil", 2) end local lowerKey = string.lower(key) for k in pairs(self) do if string.lower(k) == lowerKey then rawset(self, k, nil) rawset(self, key, value) return end end rawset(self, key, value) end } local db_mt = { __index = function(db, key) if key == "char" then if db.charName then if type(_G[db.charName]) ~= "table" then _G[db.charName] = {} end if type(_G[db.charName].raw) ~= "table" then _G[db.charName].global = {} end rawset(db, 'char', _G[db.charName].global) else if type(db.raw.chars) ~= "table" then db.raw.chars = {} end local id = charID if type(db.raw.chars[id]) ~= "table" then db.raw.chars[id] = {} end rawset(db, 'char', db.raw.chars[id]) end if db.defaults and db.defaults.char then inheritDefaults(db.char, db.defaults.char) end return db.char elseif key == "realm" then if type(db.raw.realms) ~= "table" then db.raw.realms = {} end local id = realmID if type(db.raw.realms[id]) ~= "table" then db.raw.realms[id] = {} end rawset(db, 'realm', db.raw.realms[id]) if db.defaults and db.defaults.realm then inheritDefaults(db.realm, db.defaults.realm) end return db.realm elseif key == "account" then if type(db.raw.account) ~= "table" then db.raw.account = {} end rawset(db, 'account', db.raw.account) if db.defaults and db.defaults.account then inheritDefaults(db.account, db.defaults.account) end return db.account elseif key == "class" then if type(db.raw.classes) ~= "table" then db.raw.classes = {} end local id = classID if type(db.raw.classes[id]) ~= "table" then db.raw.classes[id] = {} end rawset(db, 'class', db.raw.classes[id]) if db.defaults and db.defaults.class then inheritDefaults(db.class, db.defaults.class) end return db.class elseif key == "profile" then if type(db.raw.profiles) ~= "table" then db.raw.profiles = setmetatable({}, caseInsensitive_mt) else setmetatable(db.raw.profiles, caseInsensitive_mt) end local id = db.raw.currentProfile[charID] if id == "char" then id = "char/" .. charID elseif id == "class" then id = "class/" .. classID elseif id == "realm" then id = "realm/" .. realmID end if type(db.raw.profiles[id]) ~= "table" then db.raw.profiles[id] = {} end rawset(db, 'profile', db.raw.profiles[id]) if db.defaults and db.defaults.profile then inheritDefaults(db.profile, db.defaults.profile) end return db.profile elseif key == "raw" or key == "defaults" or key == "name" or key == "charName" or key == "namespaces" then return nil end error(string.format('Cannot access key %q in db table. You may want to use db.profile[%q]', tostring(key), tostring(key)), 2) end, __newindex = function(db, key, value) error(string.format('Cannot access key %q in db table. You may want to use db.profile[%q]', tostring(key), tostring(key)), 2) end } local namespace_mt = { __index = function(namespace, key) local db = namespace.db local name = namespace.name if key == "char" then if db.charName then if type(_G[db.charName]) ~= "table" then _G[db.charName] = {} end if type(_G[db.charName].namespaces) ~= "table" then _G[db.charName].namespaces = {} end if type(_G[db.charName].namespaces[name]) ~= "table" then _G[db.charName].namespaces[name] = {} end rawset(namespace, 'char', _G[db.charName].namespaces[name]) else if type(db.raw.namespaces) ~= "table" then db.raw.namespaces = {} end if type(db.raw.namespaces[name]) ~= "table" then db.raw.namespaces[name] = {} end if type(db.raw.namespaces[name].chars) ~= "table" then db.raw.namespaces[name].chars = {} end local id = charID if type(db.raw.namespaces[name].chars[id]) ~= "table" then db.raw.namespaces[name].chars[id] = {} end rawset(namespace, 'char', db.raw.namespaces[name].chars[id]) end if namespace.defaults and namespace.defaults.char then inheritDefaults(namespace.char, namespace.defaults.char) end return namespace.char elseif key == "realm" then if type(db.raw.namespaces) ~= "table" then db.raw.namespaces = {} end if type(db.raw.namespaces[name]) ~= "table" then db.raw.namespaces[name] = {} end if type(db.raw.namespaces[name].realms) ~= "table" then db.raw.namespaces[name].realms = {} end local id = realmID if type(db.raw.namespaces[name].realms[id]) ~= "table" then db.raw.namespaces[name].realms[id] = {} end rawset(namespace, 'realm', db.raw.namespaces[name].realms[id]) if namespace.defaults and namespace.defaults.realm then inheritDefaults(namespace.realm, namespace.defaults.realm) end return namespace.realm elseif key == "account" then if type(db.raw.namespaces) ~= "table" then db.raw.namespaces = {} end if type(db.raw.namespaces[name]) ~= "table" then db.raw.namespaces[name] = {} end if type(db.raw.namespaces[name].account) ~= "table" then db.raw.namespaces[name].account = {} end rawset(namespace, 'account', db.raw.namespaces[name].account) if namespace.defaults and namespace.defaults.account then inheritDefaults(namespace.account, namespace.defaults.account) end return namespace.account elseif key == "class" then if type(db.raw.namespaces) ~= "table" then db.raw.namespaces = {} end if type(db.raw.namespaces[name]) ~= "table" then db.raw.namespaces[name] = {} end if type(db.raw.namespaces[name].classes) ~= "table" then db.raw.namespaces[name].classes = {} end local id = classID if type(db.raw.namespaces[name].classes[id]) ~= "table" then db.raw.namespaces[name].classes[id] = {} end rawset(namespace, 'class', db.raw.namespaces[name].classes[id]) if namespace.defaults and namespace.defaults.class then inheritDefaults(namespace.class, namespace.defaults.class) end return namespace.class elseif key == "profile" then if type(db.raw.namespaces) ~= "table" then db.raw.namespaces = {} end if type(db.raw.namespaces[name]) ~= "table" then db.raw.namespaces[name] = {} end if type(db.raw.namespaces[name].profiles) ~= "table" then db.raw.namespaces[name].profiles = setmetatable({}, caseInsensitive_mt) else setmetatable(db.raw.namespaces[name].profiles, caseInsensitive_mt) end local id = db.raw.currentProfile[charID] if id == "char" then id = "char/" .. charID elseif id == "class" then id = "class/" .. classID elseif id == "realm" then id = "realm/" .. realmID end if type(db.raw.namespaces[name].profiles[id]) ~= "table" then db.raw.namespaces[name].profiles[id] = {} end rawset(namespace, 'profile', db.raw.namespaces[name].profiles[id]) if namespace.defaults and namespace.defaults.profile then inheritDefaults(namespace.profile, namespace.defaults.profile) end return namespace.profile elseif key == "defaults" or key == "name" or key == "db" then return nil end error(string.format('Cannot access key %q in db table. You may want to use db.profile[%q]', tostring(key), tostring(key)), 2) end, __newindex = function(db, key, value) error(string.format('Cannot access key %q in db table. You may want to use db.profile[%q]', tostring(key), tostring(key)), 2) end } function AceDB:InitializeDB(addonName) local db = self.db if not db then if addonName then AceDB.addonsLoaded[addonName] = true end return end if db.raw then -- someone manually initialized return end if type(_G[db.name]) ~= "table" then _G[db.name] = {} end rawset(db, 'raw', _G[db.name]) if not db.raw.currentProfile then db.raw.currentProfile = {} end if not db.raw.currentProfile[charID] then db.raw.currentProfile[charID] = "default" end if db.raw.disabled then setmetatable(db.raw.disabled, caseInsensitive_mt) end setmetatable(db, db_mt) end function AceDB:RegisterDB(name, charName) AceDB:argCheck(name, 2, "string") AceDB:argCheck(charName, 3, "string", "nil") if self.db then AceDB:error("Cannot call \"RegisterDB\" if self.db is set.") end local stack = debugstack() local addonName = string.gsub(stack, ".-\n.-\\AddOns\\(.-)\\.*", "%1") self.db = { name = name, charName = charName } if AceDB.addonsLoaded[addonName] then AceDB.InitializeDB(self, addonName) else AceDB.addonsToBeInitialized[self] = addonName end AceDB.registry[self] = true end function AceDB:RegisterDefaults(kind, defaults, a3) local name if a3 then name, kind, defaults = kind, defaults, a3 AceDB:argCheck(name, 2, "string") AceDB:argCheck(kind, 3, "string") AceDB:argCheck(defaults, 4, "table") if kind ~= "char" and kind ~= "class" and kind ~= "profile" and kind ~= "account" and kind ~= "realm" then AceDB:error("Bad argument #3 to `RegisterDefaults' (\"char\", \"class\", \"profile\", \"account\", or \"realm\" expected, got %q)", kind) end else AceDB:argCheck(kind, 2, "string") AceDB:argCheck(defaults, 3, "table") if kind ~= "char" and kind ~= "class" and kind ~= "profile" and kind ~= "account" and kind ~= "realm" then AceDB:error("Bad argument #2 to `RegisterDefaults' (\"char\", \"class\", \"profile\", \"account\", or \"realm\" expected, got %q)", kind) end end if type(self.db) ~= "table" or type(self.db.name) ~= "string" then AceDB:error("Cannot call \"RegisterDefaults\" unless \"RegisterDB\" has been previously called.") end local db if name then local namespace = self:AcquireDBNamespace(name) if namespace.defaults and namespace.defaults[kind] then AceDB:error("\"RegisterDefaults\" has already been called for %q::%q.", name, kind) end db = namespace else if self.db.defaults and self.db.defaults[kind] then AceDB:error("\"RegisterDefaults\" has already been called for %q.", kind) end db = self.db end if not db.defaults then rawset(db, 'defaults', {}) end db.defaults[kind] = defaults if rawget(db, kind) then inheritDefaults(db[kind], defaults) end end function AceDB:ResetDB(kind) AceDB:checkArg(kind, 2, "nil", "string") if not self.db or not self.db.raw then AceDB:error("Cannot call \"ResetDB\" before \"RegisterDB\" has been called and before \"ADDON_LOADED\" has been fired.") end local db = self.db if kind == nil then if db.charName then _G[db.charName] = nil end _G[db.name] = nil rawset(db, 'raw', nil) AceDB.InitializeDB(self) for name,v in pairs(db.namespaces) do rawset(v, 'account', nil) rawset(v, 'char', nil) rawset(v, 'class', nil) rawset(v, 'profile', nil) rawset(v, 'realm', nil) end elseif kind == "account" then db.raw.account = nil rawset(db, 'account', nil) for name,v in pairs(db.namespaces) do rawset(v, 'account', nil) end elseif kind == "char" then if db.charName then _G[db.charName] = nil else db.raw.chars[charID] = nil for name,v in pairs(db.raw.namespaces) do if v.chars then v.chars[charID] = nil end end end rawset(db, 'char', nil) for name,v in pairs(db.namespaces) do rawset(v, 'char', nil) end elseif kind == "realm" then db.raw.realms[realmID] = nil rawset(db, 'realm', nil) for name,v in pairs(db.raw.namespaces) do if v.realms then v.realms[realmID] = nil end end for name,v in pairs(db.namespaces) do rawset(v, 'realm', nil) end elseif kind == "class" then db.raw.realms[classID] = nil rawset(db, 'class', nil) for name,v in pairs(db.raw.namespaces) do if v.classes then v.classes[classID] = nil end end for name,v in pairs(db.namespaces) do rawset(v, 'class', nil) end elseif kind == "profile" then local id = db.raw.currentProfile[charID] if id == "char" then id = "char/" .. charID elseif id == "class" then id = "class/" .. classID elseif id == "realm" then id = "realm/" .. realmID end db.raw.profiles[id] = nil rawset(db, 'profile', nil) for name,v in pairs(db.raw.namespaces) do if v.profiles then v.profiles[id] = nil end end for name,v in pairs(db.namespaces) do rawset(v, 'profile', nil) end end end local function cleanDefaults(t, defaults) if defaults then for k,v in pairs(defaults) do if k == "*" then if type(v) == "table" then for k in pairs(t) do if (defaults[k] == nil or k == "*") and type(t[k]) == "table" then if cleanDefaults(t[k], v) then t[k] = nil end end end else for k in pairs(t) do if (defaults[k] == nil or k == "*") and t[k] == v then t[k] = nil end end end else if type(v) == "table" then if type(t[k]) == "table" then if cleanDefaults(t[k], v) then t[k] = nil end end elseif t[k] == v then t[k] = nil end end end end return not next(t) end function AceDB:GetProfile() if not self.db or not self.db.raw then return nil end local profile = self.db.raw.currentProfile[charID] if profile == "char" then return "char", "char/" .. charID elseif profile == "class" then return "class", "class/" .. classID elseif profile == "realm" then return "realm", "realm/" .. realmID end return profile, profile end local function copyTable(to, from) setmetatable(to, nil) for k,v in pairs(from) do if type(k) == "table" then k = copyTable({}, k) end if type(v) == "table" then v = copyTable({}, v) end to[k] = v end table.setn(to, table.getn(from)) setmetatable(to, from) return to end local stage = 3 if tonumber(date("%Y%m%d")) < 20060713 then stage = 1 elseif tonumber(date("%Y%m%d")) < 20060720 then stage = 2 end function AceDB:SetProfile(name, copyFrom) AceDB:argCheck(name, 2, "string") AceDB:argCheck(copyFrom, 3, "string", "nil") if not self.db or not self.db.raw then AceDB:error("Cannot call \"SetProfile\" before \"RegisterDB\" has been called and before \"ADDON_LOADED\" has been fired.") end local db = self.db local copy = false local lowerName = string.lower(name) local lowerCopyFrom = copyFrom and string.lower(copyFrom) if string.sub(lowerName, 1, 5) == "char/" or string.sub(lowerName, 1, 6) == "realm/" or string.sub(lowerName, 1, 6) == "class/" then if stage <= 2 then if string.sub(lowerName, 1, 5) == "char/" then name, copyFrom = "char", name else name, copyFrom = string.sub(lowerName, 1, 5), name end lowerName = string.lower(name) lowerCopyFrom = string.lower(copyFrom) if stage == 2 then local line = string.gsub(debugstack(), ".-\n(.-)\n.*", "%1") DEFAULT_CHAT_MESSAGE:AddMessage(line .. " - Bad argument #2 to `SetProfile'. Cannot start with char/, realm/, or class/. This will cause an error on July 20, 2006.") end else AceDB:error("Bad argument #2 to `SetProfile'. Cannot start with char/, realm/, or class/.") end end if copyFrom then if string.sub(lowerCopyFrom, 1, 5) == "char/" then AceDB:assert(lowerName == "char", "If argument #3 starts with `char/', argument #2 must be `char'") elseif string.sub(lowerCopyFrom, 1, 6) == "realm/" then AceDB:assert(lowerName == "realm", "If argument #3 starts with `realm/', argument #2 must be `realm'") elseif string.sub(lowerCopyFrom, 1, 6) == "class/" then AceDB:assert(lowerName == "class", "If argument #3 starts with `class/', argument #2 must be `class'") else AceDB:assert(lowerName ~= "char" and lowerName ~= "realm" and lowerName ~= "class", "If argument #3 does not start with a special prefix, that prefix cannot be copied to.") end if not db.raw.profiles or not db.raw.profiles[copyFrom] then AceDB:error("Cannot copy profile %q, it does not exist.", copyFrom) elseif (string.sub(lowerName, 1, 5) == "char/" and string.sub(lowerName, 6) == string.lower(charID)) or (string.sub(lowerName, 1, 6) == "realm/" and string.sub(lowerName, 7) == string.lower(realmID)) or (string.sub(lowerName, 1, 6) == "class/" and string.sub(lowerName, 7) == string.lower(classID)) then AceDB:error("Cannot copy profile %q, it is currently in use.", name) end end local oldName = db.raw.currentProfile[charID] if type(self.OnProfileDisable) == "function" then self:OnProfileDisable() end local oldProfileData = db.profile local realName = name if lowerName == "char" then realName = name .. "/" .. charID elseif lowerName == "realm/" then realName = name .. "/" .. realmID elseif lowerName == "class/" then realName = name .. "/" .. classID end local active = self:IsActive() db.raw.currentProfile[charID] = name rawset(db, 'profile', nil) if copyFrom then for k,v in pairs(db.profile) do db.profile[k] = nil end copyTable(db.profile, db.raw.profiles[copyFrom]) inheritDefaults(db.profile, db.defaults and db.defaults.profile) end if type(self.OnProfileEnable) == "function" then self:OnProfileEnable(oldName, oldProfileData) end if cleanDefaults(oldProfileData, db.defaults and db.defaults.profile) then db.raw.profiles[oldName] = nil if not next(db.raw.profiles) then db.raw.profiles = nil end end local newactive = self:IsActive() if active ~= newactive then if AceOO.inherits(self, "AceAddon-2.0") then local AceAddon = AceLibrary("AceAddon-2.0") if not AceAddon.addonsStarted[self] then return end end if newactive then if type(self.OnEnable) == "function" then self:OnEnable() end else local current = self.class while true do if current == AceOO.Class then break end if current.mixins then for mixin in pairs(current.mixins) do if type(mixin.OnEmbedDisable) == "function" then mixin:OnEmbedDisable(self) end end end current = current.super end if type(self.OnDisabled) == "function" then self:OnDisable() end end end end local stage = 3 if tonumber(date("%Y%m%d")) < 20060714 then stage = 1 elseif tonumber(date("%Y%m%d")) < 20060721 then stage = 2 end function AceDB:IsActive() return not self.db or not self.db.raw or not self.db.raw.disabled or not self.db.raw.disabled[self.db.raw.currentProfile[charID]] end function AceDB:ToggleActive(state) AceDB:argCheck(state, 2, "boolean", "nil") if not self.db or not self.db.raw then AceDB:error("Cannot call \"ToggleActive\" before \"RegisterDB\" has been called and before \"ADDON_LOADED\" has been fired.") end local db = self.db if not db.raw.disabled then db.raw.disabled = setmetatable({}, caseInsensitive_mt) end local profile = db.raw.currentProfile[charID] local disable if state == nil then disable = not db.raw.disabled[profile] else disable = not state if disable == db.raw.disabled[profile] then return end end db.raw.disabled[profile] = disable or nil if AceOO.inherits(self, "AceAddon-2.0") then local AceAddon = AceLibrary("AceAddon-2.0") if not AceAddon.addonsStarted[self] then return end end if not disable then if type(self.OnEnable) == "function" then self:OnEnable() end else local current = self.class while true do if current == AceOO.Class then break end if current.mixins then for mixin in pairs(current.mixins) do if type(mixin.OnEmbedDisable) == "function" then mixin:OnEmbedDisable(self) end end end current = current.super end if type(self.OnDisable) == "function" then self:OnDisable() end end return not disable end if stage <= 2 then function AceDB:IsEnabled() if stage == 2 then local line = string.gsub(debugstack(), ".-\n(.-)\n.*", "%1") DEFAULT_CHAT_MESSAGE:AddMessage(line .. " - :IsEnabled() has been replaced by :IsActive(). This will cause an error on July 21, 2006.") end return self:IsActive() end function AceDB:ToggleStandby() if stage == 2 then local line = string.gsub(debugstack(), ".-\n(.-)\n.*", "%1") DEFAULT_CHAT_MESSAGE:AddMessage(line .. " - :ToggleStandby() has been replaced by :ToggleActive([state]). This will cause an error on July 21, 2006.") end return self:ToggleActive() end end function AceDB:embed(target) self.super.embed(self, target) if not AceEvent then AceDB:error(MAJOR_VERSION .. " requires AceEvent-2.0") end end function AceDB:ADDON_LOADED(name) AceDB.addonsLoaded[name] = true for addon, addonName in pairs(AceDB.addonsToBeInitialized) do if name == addonName then AceDB.InitializeDB(addon, name) AceDB.addonsToBeInitialized[addon] = nil end end end function AceDB:PLAYER_LOGOUT() for addon in pairs(AceDB.registry) do local db = addon.db if db then setmetatable(db, nil) if db.char and cleanDefaults(db.char, db.defaults and db.defaults.char) then if db.charName and _G[db.charName].global == db.char then _G[db.charName].global = nil if not next(_G[db.charName]) then _G[db.charName] = nil end else db.raw.chars[charID] = nil if not next(db.raw.chars) then db.raw.chars = nil end end end if db.realm and cleanDefaults(db.realm, db.defaults and db.defaults.realm) then db.raw.realms[realmID] = nil if not next(db.raw.realms) then db.raw.realms = nil end end if db.class and cleanDefaults(db.class, db.defaults and db.defaults.class) then db.raw.classes[classID] = nil if not next(db.raw.classes) then db.raw.classes = nil end end if db.account and cleanDefaults(db.account, db.defaults and db.defaults.account) then db.raw.account = nil end if db.profile and cleanDefaults(db.profile, db.defaults and db.defaults.profile) then db.raw.profiles[db.raw.currentProfile[charID] or "default"] = nil if not next(db.raw.profiles) then db.raw.profiles = nil end end if db.namespaces then for name,v in pairs(db.namespaces) do setmetatable(v, nil) if v.char and cleanDefaults(v.char, v.defaults and v.defaults.char) then if db.charName and _G[db.charName] and _G[db.charName].namespaces and _G[db.charName].namespaces[name] == v then _G[db.charName].namespaces[name] = nil if not next(_G[db.charName].namespaces) then _G[db.charName].namespaces = nil if not next(_G[db.charName]) then _G[db.charName] = nil end end else db.raw.namespaces[name].chars[charID] = nil if not next(db.raw.namespaces[name].chars) then db.raw.namespaces[name].chars = nil end end end if v.realm and cleanDefaults(v.realm, v.defaults and v.defaults.realm) then db.raw.namespaces[name].realms[realmID] = nil if not next(db.raw.namespaces[name].realms) then db.raw.namespaces[name].realms = nil end end if v.class and cleanDefaults(v.class, v.defaults and v.defaults.class) then db.raw.namespaces[name].classes[classID] = nil if not next(db.raw.namespaces[name].classes) then db.raw.namespaces[name].classes = nil end end if v.account and cleanDefaults(v.account, v.defaults and v.defaults.account) then db.raw.namespaces[name].account = nil end if v.profile and cleanDefaults(v.profile, v.defaults and v.defaults.profile) then db.raw.namespaces[name].profiles[db.raw.currentProfile[charID] or "default"] = nil if not next(db.raw.namespaces[name].profiles) then db.raw.namespaces[name].profiles = nil end end if not next(db.raw.namespaces[name]) then db.raw.namespaces[name] = nil end end if not next(db.raw.namespaces) then db.raw.namespaces = nil end end if db.raw.disabled then if not next(db.raw.disabled) then db.raw.disabled = nil end end if db.raw.currentProfile then for k,v in pairs(db.raw.currentProfile) do if string.lower(v) == "default" then db.raw.currentProfile[k] = nil end end if not next(db.raw.currentProfile) then db.raw.currentProfile = nil end end if not next(db.raw) then _G[db.name] = nil end end end end function AceDB:AcquireDBNamespace(name) AceDB:argCheck(name, 2, "string") local db = self.db if not db then AceDB:error("Cannot call `AcquireDBNamespace' before `RegisterDB' has been called.", 2) end if not db.namespaces then rawset(db, 'namespaces', {}) end if not db.namespaces[name] then local namespace = {} db.namespaces[name] = namespace namespace.db = db namespace.name = name setmetatable(namespace, namespace_mt) end return db.namespaces[name] end local options function AceDB:GetAceOptionsDataTable(target) if not options then options = { standby = { cmdName = STATE, guiName = ACTIVE, name = ACTIVE, desc = TOGGLE_ACTIVE, type = "toggle", get = "IsActive", set = "ToggleActive", map = MAP_ACTIVESUSPENDED, }, profile = { name = PROFILE, desc = SET_PROFILE, get = "GetProfile", set = "SetProfile", usage = SET_PROFILE_USAGE, type = "text", validate = function(x) return not tonumber(x) end, } } end return options end local function activate(self, oldLib, oldDeactivate) AceDB = self AceEvent = AceLibrary:HasInstance("AceEvent-2.0") and AceLibrary("AceEvent-2.0") self.super.activate(self, oldLib, oldDeactivate) for t in pairs(self.embedList) do if t.db then rawset(t.db, 'char', nil) rawset(t.db, 'realm', nil) rawset(t.db, 'class', nil) rawset(t.db, 'account', nil) rawset(t.db, 'profile', nil) setmetatable(t.db, db_mt) end end if oldLib then self.addonsToBeInitialized = oldLib.addonsToBeInitialized self.addonsLoaded = oldLib.addonsLoaded self.registry = oldLib.registry end if not self.addonsToBeInitialized then self.addonsToBeInitialized = {} end if not self.addonsLoaded then self.addonsLoaded = {} end if not self.registry then self.registry = {} end if oldLib then oldDeactivate(oldLib) end end local function external(self, major, instance) if major == "AceEvent-2.0" then AceEvent = instance AceEvent:embed(self) self:RegisterEvent("ADDON_LOADED") self:RegisterEvent("PLAYER_LOGOUT") end end AceLibrary:Register(AceDB, MAJOR_VERSION, MINOR_VERSION, activate, nil, external) AceDB = AceLibrary(MAJOR_VERSION)