comparison libs/AceDB-2.0/AceDB-2.0.lua @ 1:c11ca1d8ed91

Version 0.1
author Flick <flickerstreak@gmail.com>
date Tue, 20 Mar 2007 21:03:57 +0000
parents
children
comparison
equal deleted inserted replaced
0:4e2ce2894c21 1:c11ca1d8ed91
1 --[[
2 Name: AceDB-2.0
3 Revision: $Rev: 18708 $
4 Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
5 Inspired By: Ace 1.x by Turan (turan@gryphon.com)
6 Website: http://www.wowace.com/
7 Documentation: http://www.wowace.com/index.php/AceDB-2.0
8 SVN: http://svn.wowace.com/root/trunk/Ace2/AceDB-2.0
9 Description: Mixin to allow for fast, clean, and featureful saved variable
10 access.
11 Dependencies: AceLibrary, AceOO-2.0, AceEvent-2.0
12 ]]
13
14 local MAJOR_VERSION = "AceDB-2.0"
15 local MINOR_VERSION = "$Revision: 18708 $"
16
17 if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end
18 if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
19
20 if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end
21
22 local function safecall(func,...)
23 local success, err = pcall(func,...)
24 if not success then geterrorhandler()(err) end
25 end
26
27 local ACTIVE, ENABLED, STATE, TOGGLE_ACTIVE, MAP_ACTIVESUSPENDED, SET_PROFILE, SET_PROFILE_USAGE, PROFILE, PLAYER_OF_REALM, CHOOSE_PROFILE_DESC, CHOOSE_PROFILE_GUI, COPY_PROFILE_DESC, COPY_PROFILE_GUI, OTHER_PROFILE_DESC, OTHER_PROFILE_GUI, OTHER_PROFILE_USAGE, CHARACTER_COLON, REALM_COLON, CLASS_COLON, DEFAULT, ALTERNATIVE
28
29 if GetLocale() == "deDE" then
30 ACTIVE = "Aktiv"
31 ENABLED = "Aktiviert"
32 STATE = "Status"
33 TOGGLE_ACTIVE = "Stoppt/Aktiviert dieses Addon."
34 MAP_ACTIVESUSPENDED = { [true] = "|cff00ff00Aktiv|r", [false] = "|cffff0000Gestoppt|r" }
35 SET_PROFILE = "Setzt das Profil f\195\188r dieses Addon."
36 SET_PROFILE_USAGE = "{Charakter || Klasse || Realm || <Profilname>}"
37 PROFILE = "Profil"
38 PLAYER_OF_REALM = "%s von %s"
39 CHOOSE_PROFILE_DESC = "W\195\164hle ein Profil."
40 CHOOSE_PROFILE_GUI = "W\195\164hle"
41 COPY_PROFILE_DESC = "Kopiert Einstellungen von einem anderem Profil."
42 COPY_PROFILE_GUI = "Kopiere von"
43 OTHER_PROFILE_DESC = "W\195\164hle ein anderes Profil."
44 OTHER_PROFILE_GUI = "Anderes"
45 OTHER_PROFILE_USAGE = "<Profilname>"
46
47 CHARACTER_COLON = "Charakter: "
48 REALM_COLON = "Realm: "
49 CLASS_COLON = "Klasse: "
50
51 DEFAULT = "Default" -- fix
52 ALTERNATIVE = "Alternative" -- fix
53 elseif GetLocale() == "frFR" then
54 ACTIVE = "Actif"
55 ENABLED = "Activ\195\169"
56 STATE = "Etat"
57 TOGGLE_ACTIVE = "Suspend/active cet addon."
58 MAP_ACTIVESUSPENDED = { [true] = "|cff00ff00Actif|r", [false] = "|cffff0000Suspendu|r" }
59 SET_PROFILE = "S\195\169lectionne le profil pour cet addon."
60 SET_PROFILE_USAGE = "{perso || classe || royaume || <nom de profil>}"
61 PROFILE = "Profil"
62 PLAYER_OF_REALM = "%s de %s"
63 CHOOSE_PROFILE_DESC = "Choisissez un profil."
64 CHOOSE_PROFILE_GUI = "Choix"
65 COPY_PROFILE_DESC = "Copier les param\195\168tres d'un autre profil."
66 COPY_PROFILE_GUI = "Copier \195\160 partir de"
67 OTHER_PROFILE_DESC = "Choisissez un autre profil."
68 OTHER_PROFILE_GUI = "Autre"
69 OTHER_PROFILE_USAGE = "<nom de profil>"
70
71 CHARACTER_COLON = "Personnage: "
72 REALM_COLON = "Royaume: "
73 CLASS_COLON = "Classe: "
74
75 DEFAULT = "Default" -- fix
76 ALTERNATIVE = "Alternative" -- fix
77 elseif GetLocale() == "koKR" then
78 ACTIVE = "활성화"
79 ENABLED = "활성화"
80 STATE = "상태"
81 TOGGLE_ACTIVE = "이 애드온 중지/계속 실행"
82 MAP_ACTIVESUSPENDED = { [true] = "|cff00ff00활성화|r", [false] = "|cffff0000중지됨|r" }
83 SET_PROFILE = "이 애드온에 프로필 설정"
84 SET_PROFILE_USAGE = "{캐릭터명 || 직업 || 서버명 || <프로필명>}"
85 PROFILE = "프로필"
86 PLAYER_OF_REALM = "%s (%s 서버)"
87 CHOOSE_PROFILE_DESC = "프로파일을 선택합니다."
88 CHOOSE_PROFILE_GUI = "선택"
89 COPY_PROFILE_DESC = "다른 프로파일에서 설정을 복사합니다."
90 COPY_PROFILE_GUI = "복사"
91 OTHER_PROFILE_DESC = "다른 프로파일을 선택합니다."
92 OTHER_PROFILE_GUI = "기타"
93 OTHER_PROFILE_USAGE = "<프로파일명>"
94
95 CHARACTER_COLON = "캐릭터: "
96 REALM_COLON = "서버: "
97 CLASS_COLON = "직업: "
98
99 DEFAULT = "Default" -- fix
100 ALTERNATIVE = "Alternative" -- fix
101 elseif GetLocale() == "zhTW" then
102 ACTIVE = "啟動"
103 ENABLED = "啟用"
104 STATE = "狀態"
105 TOGGLE_ACTIVE = "暫停/重啟這個插件。"
106 MAP_ACTIVESUSPENDED = { [true] = "|cff00ff00啟動|r", [false] = "|cffff0000已暫停|r" }
107 SET_PROFILE = "設定這插件的記錄檔。"
108 SET_PROFILE_USAGE = "{角色 || 聯業 || 伺服器 || <記錄檔名稱>}"
109 PROFILE = "記錄檔"
110 PLAYER_OF_REALM = "%s 於 %s"
111 CHOOSE_PROFILE_DESC = "選擇一個記錄檔"
112 CHOOSE_PROFILE_GUI = "選擇"
113 COPY_PROFILE_DESC = "由其他記錄檔複製設定。"
114 COPY_PROFILE_GUI = "複製由"
115 OTHER_PROFILE_DESC = "選擇其他記錄檔。"
116 OTHER_PROFILE_GUI = "其他"
117 OTHER_PROFILE_USAGE = "<記錄檔名稱>"
118
119 CHARACTER_COLON = "角色:"
120 REALM_COLON = "伺服器:"
121 CLASS_COLON = "聯業:"
122
123 DEFAULT = "Default" -- fix
124 ALTERNATIVE = "Alternative" -- fix
125 elseif GetLocale() == "zhCN" then
126 ACTIVE = "\230\156\137\230\149\136"
127 ENABLED = "\229\144\175\231\148\168"
128 STATE = "\231\138\182\230\128\129"
129 TOGGLE_ACTIVE = "\230\154\130\229\129\156/\230\129\162\229\164\141 \230\173\164\230\143\146\228\187\182."
130 MAP_ACTIVESUSPENDED = { [true] = "|cff00ff00\230\156\137\230\149\136|r", [false] = "|cffff0000\230\154\130\229\129\156|r" }
131 SET_PROFILE = "\232\174\190\231\189\174\233\133\141\231\189\174\230\150\135\228\187\182\228\184\186\232\191\153\230\143\146\228\187\182."
132 SET_PROFILE_USAGE = "{\229\173\151\231\172\166 || \233\128\137\228\187\182\231\177\187 || \229\159\159 || <\233\133\141\231\189\174\230\150\135\228\187\182\229\144\141\229\173\151>}"
133 PROFILE = "\233\133\141\231\189\174\230\150\135\228\187\182"
134 PLAYER_OF_REALM = "%s \231\154\132 %s"
135 CHOOSE_PROFILE_DESC = "\233\128\137\230\139\169\233\133\141\231\189\174\230\150\135\228\187\182."
136 CHOOSE_PROFILE_GUI = "\233\128\137\230\139\169"
137 COPY_PROFILE_DESC = "\229\164\141\229\136\182\232\174\190\231\189\174\228\187\142\229\143\166\228\184\128\228\184\170\233\133\141\231\189\174\230\150\135\228\187\182."
138 COPY_PROFILE_GUI = "\229\164\141\229\136\182\228\187\142"
139 OTHER_PROFILE_DESC = "\233\128\137\230\139\169\229\143\166\228\184\128\228\184\170\233\133\141\231\189\174\230\150\135\228\187\182."
140 OTHER_PROFILE_GUI = "\229\133\182\228\187\150"
141 OTHER_PROFILE_USAGE = "<\233\133\141\231\189\174\230\150\135\228\187\182\229\144\141\229\173\151>"
142
143 CHARACTER_COLON = "\229\173\151\231\172\166: "
144 REALM_COLON = "\229\159\159: "
145 CLASS_COLON = "\233\128\137\228\187\182\231\177\187: "
146
147 DEFAULT = "Default" -- fix
148 ALTERNATIVE = "Alternative" -- fix
149 else -- enUS
150 ACTIVE = "Active"
151 ENABLED = "Enabled"
152 STATE = "State"
153 TOGGLE_ACTIVE = "Suspend/resume this addon."
154 MAP_ACTIVESUSPENDED = { [true] = "|cff00ff00Active|r", [false] = "|cffff0000Suspended|r" }
155 SET_PROFILE = "Set profile for this addon."
156 SET_PROFILE_USAGE = "{char || class || realm || <profile name>}"
157 PROFILE = "Profile"
158 PLAYER_OF_REALM = "%s of %s"
159 CHOOSE_PROFILE_DESC = "Choose a profile."
160 CHOOSE_PROFILE_GUI = "Choose"
161 COPY_PROFILE_DESC = "Copy settings from another profile."
162 COPY_PROFILE_GUI = "Copy from"
163 OTHER_PROFILE_DESC = "Choose another profile."
164 OTHER_PROFILE_GUI = "Other"
165 OTHER_PROFILE_USAGE = "<profile name>"
166
167 CHARACTER_COLON = "Character: "
168 REALM_COLON = "Realm: "
169 CLASS_COLON = "Class: "
170
171 DEFAULT = "Default"
172 ALTERNATIVE = "Alternative"
173 end
174
175 local AceOO = AceLibrary("AceOO-2.0")
176 local AceEvent
177 local Mixin = AceOO.Mixin
178 local AceDB = Mixin {
179 "RegisterDB",
180 "RegisterDefaults",
181 "ResetDB",
182 "SetProfile",
183 "GetProfile",
184 "CopyProfileFrom",
185 "ToggleActive",
186 "IsActive",
187 "AcquireDBNamespace",
188 }
189 local Dewdrop = AceLibrary:HasInstance("Dewdrop-2.0") and AceLibrary("Dewdrop-2.0")
190
191 local _G = getfenv(0)
192
193 local function inheritDefaults(t, defaults)
194 if not defaults then
195 return t
196 end
197 for k,v in pairs(defaults) do
198 if k == "*" then
199 local v = v
200 if type(v) == "table" then
201 setmetatable(t, {
202 __index = function(self, key)
203 if key == nil then
204 return nil
205 end
206 self[key] = {}
207 inheritDefaults(self[key], v)
208 return self[key]
209 end
210 } )
211 else
212 setmetatable(t, {
213 __index = function(self, key)
214 if key == nil then
215 return nil
216 end
217 self[key] = v
218 return self[key]
219 end
220 } )
221 end
222 for key in pairs(t) do
223 if (defaults[key] == nil or key == "*") and type(t[key]) == "table" then
224 inheritDefaults(t[key], v)
225 end
226 end
227 else
228 if type(v) == "table" then
229 if type(t[k]) ~= "table" then
230 t[k] = {}
231 end
232 inheritDefaults(t[k], v)
233 elseif t[k] == nil then
234 t[k] = v
235 end
236 end
237 end
238 return t
239 end
240
241 local _,race = UnitRace("player")
242 local faction
243 if race == "Orc" or race == "Scourge" or race == "Troll" or race == "Tauren" or race == "BloodElf" then
244 faction = FACTION_HORDE
245 else
246 faction = FACTION_ALLIANCE
247 end
248 local charID = string.format(PLAYER_OF_REALM, UnitName("player"), (string.gsub(GetRealmName(), "^%s*(.-)%s*$", "%1")))
249 local realm = string.gsub(GetRealmName(), "^%s*(.-)%s*$", "%1")
250 local realmID = realm .. " - " .. faction
251 local classID = UnitClass("player")
252
253 AceDB.CHAR_ID = charID
254 AceDB.REALM_ID = realmID
255 AceDB.CLASS_ID = classID
256
257 AceDB.FACTION = faction
258 AceDB.REALM = realm
259 AceDB.NAME = UnitName("player")
260
261 local new, del
262 do
263 local list = setmetatable({}, {__mode="k"})
264 function new()
265 local t = next(list)
266 if t then
267 list[t] = nil
268 return t
269 else
270 return {}
271 end
272 end
273
274 function del(t)
275 setmetatable(t, nil)
276 for k in pairs(t) do
277 t[k] = nil
278 end
279 list[t] = true
280 end
281 end
282
283 local caseInsensitive_mt = {
284 __index = function(self, key)
285 if type(key) ~= "string" then
286 return nil
287 end
288 local lowerKey = string.lower(key)
289 for k,v in pairs(self) do
290 if string.lower(k) == lowerKey then
291 return self[k]
292 end
293 end
294 end,
295 __newindex = function(self, key, value)
296 if type(key) ~= "string" then
297 return error("table index is nil", 2)
298 end
299 local lowerKey = string.lower(key)
300 for k in pairs(self) do
301 if string.lower(k) == lowerKey then
302 rawset(self, k, nil)
303 rawset(self, key, value)
304 return
305 end
306 end
307 rawset(self, key, value)
308 end
309 }
310
311 local db_mt = { __index = function(db, key)
312 if key == "char" then
313 if db.charName then
314 if type(_G[db.charName]) ~= "table" then
315 _G[db.charName] = {}
316 end
317 if type(_G[db.charName].global) ~= "table" then
318 _G[db.charName].global = {}
319 end
320 rawset(db, 'char', _G[db.charName].global)
321 else
322 if type(db.raw.chars) ~= "table" then
323 db.raw.chars = {}
324 end
325 local id = charID
326 if type(db.raw.chars[id]) ~= "table" then
327 db.raw.chars[id] = {}
328 end
329 rawset(db, 'char', db.raw.chars[id])
330 end
331 if db.defaults and db.defaults.char then
332 inheritDefaults(db.char, db.defaults.char)
333 end
334 return db.char
335 elseif key == "realm" then
336 if type(db.raw.realms) ~= "table" then
337 db.raw.realms = {}
338 end
339 local id = realmID
340 if type(db.raw.realms[id]) ~= "table" then
341 db.raw.realms[id] = {}
342 end
343 rawset(db, 'realm', db.raw.realms[id])
344 if db.defaults and db.defaults.realm then
345 inheritDefaults(db.realm, db.defaults.realm)
346 end
347 return db.realm
348 elseif key == "account" then
349 if type(db.raw.account) ~= "table" then
350 db.raw.account = {}
351 end
352 rawset(db, 'account', db.raw.account)
353 if db.defaults and db.defaults.account then
354 inheritDefaults(db.account, db.defaults.account)
355 end
356 return db.account
357 elseif key == "faction" then
358 if type(db.raw.factions) ~= "table" then
359 db.raw.factions = {}
360 end
361 local id = faction
362 if type(db.raw.factions[id]) ~= "table" then
363 db.raw.factions[id] = {}
364 end
365 rawset(db, 'faction', db.raw.factions[id])
366 if db.defaults and db.defaults.faction then
367 inheritDefaults(db.faction, db.defaults.faction)
368 end
369 return db.faction
370 elseif key == "class" then
371 if type(db.raw.classes) ~= "table" then
372 db.raw.classes = {}
373 end
374 local id = classID
375 if type(db.raw.classes[id]) ~= "table" then
376 db.raw.classes[id] = {}
377 end
378 rawset(db, 'class', db.raw.classes[id])
379 if db.defaults and db.defaults.class then
380 inheritDefaults(db.class, db.defaults.class)
381 end
382 return db.class
383 elseif key == "profile" then
384 if type(db.raw.profiles) ~= "table" then
385 db.raw.profiles = setmetatable({}, caseInsensitive_mt)
386 else
387 setmetatable(db.raw.profiles, caseInsensitive_mt)
388 end
389 local id = db.raw.currentProfile[charID]
390 if id == "char" then
391 id = "char/" .. charID
392 elseif id == "class" then
393 id = "class/" .. classID
394 elseif id == "realm" then
395 id = "realm/" .. realmID
396 end
397 if type(db.raw.profiles[id]) ~= "table" then
398 db.raw.profiles[id] = {}
399 end
400 rawset(db, 'profile', db.raw.profiles[id])
401 if db.defaults and db.defaults.profile then
402 inheritDefaults(db.profile, db.defaults.profile)
403 end
404 return db.profile
405 elseif key == "raw" or key == "defaults" or key == "name" or key == "charName" or key == "namespaces" then
406 return nil
407 end
408 error(string.format('Cannot access key %q in db table. You may want to use db.profile[%q]', tostring(key), tostring(key)), 2)
409 end, __newindex = function(db, key, value)
410 error(string.format('Cannot access key %q in db table. You may want to use db.profile[%q]', tostring(key), tostring(key)), 2)
411 end }
412
413 local function RecalculateAceDBCopyFromList(target)
414 local db = target.db
415 local t = target['acedb-profile-copylist']
416 for k,v in pairs(t) do
417 t[k] = nil
418 end
419 local _,currentProfile = AceDB.GetProfile(target)
420 if db and db.raw then
421 if db.raw.profiles then
422 for k in pairs(db.raw.profiles) do
423 if currentProfile ~= k then
424 if string.find(k, '^char/') then
425 local name = string.sub(k, 6)
426 t[k] = CHARACTER_COLON .. name
427 elseif string.find(k, '^realm/') then
428 local name = string.sub(k, 7)
429 t[k] = REALM_COLON .. name
430 elseif string.find(k, '^class/') then
431 local name = string.sub(k, 7)
432 t[k] = CLASS_COLON .. name
433 else
434 t[k] = k
435 end
436 end
437 end
438 end
439 if db.raw.namespaces then
440 for _,n in pairs(db.raw.namespaces) do
441 if n.profiles then
442 for k in pairs(n.profiles) do
443 if currentProfile ~= k then
444 if string.find(k, '^char/') then
445 local name = string.sub(k, 6)
446 t[k] = CHARACTER_COLON .. name
447 elseif string.find(k, '^realm/') then
448 local name = string.sub(k, 7)
449 t[k] = REALM_COLON .. name
450 elseif string.find(k, '^class/') then
451 local name = string.sub(k, 7)
452 t[k] = CLASS_COLON .. name
453 else
454 t[k] = k
455 end
456 end
457 end
458 end
459 end
460 end
461 end
462 if t.Default then
463 t.Default = DEFAULT
464 end
465 if t.Alternative then
466 t.Alternative = ALTERNATIVE
467 end
468 end
469
470 local function RecalculateAceDBProfileList(target)
471 local t = target['acedb-profile-list']
472 for k,v in pairs(t) do
473 t[k] = nil
474 end
475 t.char = CHARACTER_COLON .. charID
476 t.realm = REALM_COLON .. realmID
477 t.class = CLASS_COLON .. classID
478 t.Default = DEFAULT
479 local db = target.db
480 if db and db.raw then
481 if db.raw.profiles then
482 for k in pairs(db.raw.profiles) do
483 if not string.find(k, '^char/') and not string.find(k, '^realm/') and not string.find(k, '^class/') then
484 t[k] = k
485 end
486 end
487 end
488 if db.raw.namespaces then
489 for _,n in pairs(db.raw.namespaces) do
490 if n.profiles then
491 for k in pairs(n.profiles) do
492 if not string.find(k, '^char/') and not string.find(k, '^realm/') and not string.find(k, '^class/') then
493 t[k] = k
494 end
495 end
496 end
497 end
498 end
499 local curr = db.raw.currentProfile and db.raw.currentProfile[charID]
500 if curr then
501 t[curr] = curr
502 end
503 end
504 if t.Alternative then
505 t.Alternative = ALTERNATIVE
506 end
507 end
508
509 local CrawlForSerialization
510 local CrawlForDeserialization
511
512 local function SerializeObject(o)
513 local t = { o:Serialize() }
514 CrawlForSerialization(t)
515 t[0] = o.class:GetLibraryVersion()
516 return t
517 end
518
519 local function DeserializeObject(t)
520 CrawlForDeserialization(t)
521 local className = t[0]
522 t[0] = nil
523 return AceLibrary(className):Deserialize(unpack(t))
524 end
525
526 local function IsSerializable(t)
527 return AceOO.inherits(t, AceOO.Class) and t.class and type(t.class.Deserialize) == "function" and type(t.Serialize) == "function" and type(t.class.GetLibraryVersion) == "function"
528 end
529
530 function CrawlForSerialization(t)
531 local tmp = new()
532 for k,v in pairs(t) do
533 tmp[k] = v
534 end
535 for k,v in pairs(tmp) do
536 if type(v) == "table" and type(v[0]) ~= "userdata" then
537 if IsSerializable(v) then
538 v = SerializeObject(v)
539 t[k] = v
540 else
541 CrawlForSerialization(v)
542 end
543 end
544 if type(k) == "table" and type(k[0]) ~= "userdata" then
545 if IsSerializable(k) then
546 t[k] = nil
547 t[SerializeObject(k)] = v
548 else
549 CrawlForSerialization(k)
550 end
551 end
552 tmp[k] = nil
553 k = nil
554 end
555 tmp = del(tmp)
556 end
557
558 local function IsDeserializable(t)
559 return type(t[0]) == "string" and AceLibrary:HasInstance(t[0])
560 end
561
562 function CrawlForDeserialization(t)
563 local tmp = new()
564 for k,v in pairs(t) do
565 tmp[k] = v
566 end
567 for k,v in pairs(tmp) do
568 if type(v) == "table" then
569 if IsDeserializable(v) then
570 t[k] = DeserializeObject(v)
571 del(v)
572 v = t[k]
573 elseif type(v[0]) ~= "userdata" then
574 CrawlForDeserialization(v)
575 end
576 end
577 if type(k) == "table" then
578 if IsDeserializable(k) then
579 t[k] = nil
580 t[DeserializeObject(k)] = v
581 del(k)
582 elseif type(k[0]) ~= "userdata" then
583 CrawlForDeserialization(k)
584 end
585 end
586 tmp[k] = nil
587 k = nil
588 end
589 tmp = del(tmp)
590 end
591
592 local namespace_mt = { __index = function(namespace, key)
593 local db = namespace.db
594 local name = namespace.name
595 if key == "char" then
596 if db.charName then
597 if type(_G[db.charName]) ~= "table" then
598 _G[db.charName] = {}
599 end
600 if type(_G[db.charName].namespaces) ~= "table" then
601 _G[db.charName].namespaces = {}
602 end
603 if type(_G[db.charName].namespaces[name]) ~= "table" then
604 _G[db.charName].namespaces[name] = {}
605 end
606 rawset(namespace, 'char', _G[db.charName].namespaces[name])
607 else
608 if type(db.raw.namespaces) ~= "table" then
609 db.raw.namespaces = {}
610 end
611 if type(db.raw.namespaces[name]) ~= "table" then
612 db.raw.namespaces[name] = {}
613 end
614 if type(db.raw.namespaces[name].chars) ~= "table" then
615 db.raw.namespaces[name].chars = {}
616 end
617 local id = charID
618 if type(db.raw.namespaces[name].chars[id]) ~= "table" then
619 db.raw.namespaces[name].chars[id] = {}
620 end
621 rawset(namespace, 'char', db.raw.namespaces[name].chars[id])
622 end
623 if namespace.defaults and namespace.defaults.char then
624 inheritDefaults(namespace.char, namespace.defaults.char)
625 end
626 return namespace.char
627 elseif key == "realm" then
628 if type(db.raw.namespaces) ~= "table" then
629 db.raw.namespaces = {}
630 end
631 if type(db.raw.namespaces[name]) ~= "table" then
632 db.raw.namespaces[name] = {}
633 end
634 if type(db.raw.namespaces[name].realms) ~= "table" then
635 db.raw.namespaces[name].realms = {}
636 end
637 local id = realmID
638 if type(db.raw.namespaces[name].realms[id]) ~= "table" then
639 db.raw.namespaces[name].realms[id] = {}
640 end
641 rawset(namespace, 'realm', db.raw.namespaces[name].realms[id])
642 if namespace.defaults and namespace.defaults.realm then
643 inheritDefaults(namespace.realm, namespace.defaults.realm)
644 end
645 return namespace.realm
646 elseif key == "account" then
647 if type(db.raw.namespaces) ~= "table" then
648 db.raw.namespaces = {}
649 end
650 if type(db.raw.namespaces[name]) ~= "table" then
651 db.raw.namespaces[name] = {}
652 end
653 if type(db.raw.namespaces[name].account) ~= "table" then
654 db.raw.namespaces[name].account = {}
655 end
656 rawset(namespace, 'account', db.raw.namespaces[name].account)
657 if namespace.defaults and namespace.defaults.account then
658 inheritDefaults(namespace.account, namespace.defaults.account)
659 end
660 return namespace.account
661 elseif key == "faction" then
662 if type(db.raw.namespaces) ~= "table" then
663 db.raw.namespaces = {}
664 end
665 if type(db.raw.namespaces[name]) ~= "table" then
666 db.raw.namespaces[name] = {}
667 end
668 if type(db.raw.namespaces[name].factions) ~= "table" then
669 db.raw.namespaces[name].factions = {}
670 end
671 local id = faction
672 if type(db.raw.namespaces[name].factions[id]) ~= "table" then
673 db.raw.namespaces[name].factions[id] = {}
674 end
675 rawset(namespace, 'faction', db.raw.namespaces[name].factions[id])
676 if namespace.defaults and namespace.defaults.faction then
677 inheritDefaults(namespace.faction, namespace.defaults.faction)
678 end
679 return namespace.faction
680 elseif key == "class" then
681 if type(db.raw.namespaces) ~= "table" then
682 db.raw.namespaces = {}
683 end
684 if type(db.raw.namespaces[name]) ~= "table" then
685 db.raw.namespaces[name] = {}
686 end
687 if type(db.raw.namespaces[name].classes) ~= "table" then
688 db.raw.namespaces[name].classes = {}
689 end
690 local id = classID
691 if type(db.raw.namespaces[name].classes[id]) ~= "table" then
692 db.raw.namespaces[name].classes[id] = {}
693 end
694 rawset(namespace, 'class', db.raw.namespaces[name].classes[id])
695 if namespace.defaults and namespace.defaults.class then
696 inheritDefaults(namespace.class, namespace.defaults.class)
697 end
698 return namespace.class
699 elseif key == "profile" then
700 if type(db.raw.namespaces) ~= "table" then
701 db.raw.namespaces = {}
702 end
703 if type(db.raw.namespaces[name]) ~= "table" then
704 db.raw.namespaces[name] = {}
705 end
706 if type(db.raw.namespaces[name].profiles) ~= "table" then
707 db.raw.namespaces[name].profiles = setmetatable({}, caseInsensitive_mt)
708 else
709 setmetatable(db.raw.namespaces[name].profiles, caseInsensitive_mt)
710 end
711 local id = db.raw.currentProfile[charID]
712 if id == "char" then
713 id = "char/" .. charID
714 elseif id == "class" then
715 id = "class/" .. classID
716 elseif id == "realm" then
717 id = "realm/" .. realmID
718 end
719 if type(db.raw.namespaces[name].profiles[id]) ~= "table" then
720 db.raw.namespaces[name].profiles[id] = {}
721 end
722 rawset(namespace, 'profile', db.raw.namespaces[name].profiles[id])
723 if namespace.defaults and namespace.defaults.profile then
724 inheritDefaults(namespace.profile, namespace.defaults.profile)
725 end
726 return namespace.profile
727 elseif key == "defaults" or key == "name" or key == "db" then
728 return nil
729 end
730 error(string.format('Cannot access key %q in db table. You may want to use db.profile[%q]', tostring(key), tostring(key)), 2)
731 end, __newindex = function(db, key, value)
732 error(string.format('Cannot access key %q in db table. You may want to use db.profile[%q]', tostring(key), tostring(key)), 2)
733 end }
734
735 function AceDB:InitializeDB(addonName)
736 local db = self.db
737
738 if not db then
739 if addonName then
740 AceDB.addonsLoaded[addonName] = true
741 end
742 return
743 end
744
745 if db.raw then
746 -- someone manually initialized
747 return
748 end
749
750 if type(_G[db.name]) ~= "table" then
751 _G[db.name] = {}
752 else
753 CrawlForDeserialization(_G[db.name])
754 end
755 if type(_G[db.charName]) == "table" then
756 CrawlForDeserialization(_G[db.charName])
757 end
758 rawset(db, 'raw', _G[db.name])
759 if not db.raw.currentProfile then
760 db.raw.currentProfile = {}
761 end
762 if not db.raw.currentProfile[charID] then
763 db.raw.currentProfile[charID] = "Default"
764 end
765 if db.raw.disabled then
766 setmetatable(db.raw.disabled, caseInsensitive_mt)
767 end
768 if self['acedb-profile-copylist'] then
769 RecalculateAceDBCopyFromList(self)
770 end
771 if self['acedb-profile-list'] then
772 RecalculateAceDBProfileList(self)
773 end
774 setmetatable(db, db_mt)
775 end
776
777 function AceDB:OnEmbedInitialize(target, name)
778 if name then
779 self:ADDON_LOADED(name)
780 end
781 self.InitializeDB(target, name)
782 end
783
784 function AceDB:RegisterDB(name, charName)
785 AceDB:argCheck(name, 2, "string")
786 AceDB:argCheck(charName, 3, "string", "nil")
787 if self.db then
788 AceDB:error("Cannot call \"RegisterDB\" if self.db is set.")
789 end
790 local stack = debugstack()
791 local addonName = string.gsub(stack, ".-\n.-\\AddOns\\(.-)\\.*", "%1")
792 self.db = {
793 name = name,
794 charName = charName
795 }
796 if AceDB.addonsLoaded[addonName] then
797 AceDB.InitializeDB(self, addonName)
798 else
799 AceDB.addonsToBeInitialized[self] = addonName
800 end
801 AceDB.registry[self] = true
802 end
803
804 function AceDB:RegisterDefaults(kind, defaults, a3)
805 local name
806 if a3 then
807 name, kind, defaults = kind, defaults, a3
808 AceDB:argCheck(name, 2, "string")
809 AceDB:argCheck(kind, 3, "string")
810 AceDB:argCheck(defaults, 4, "table")
811 else
812 AceDB:argCheck(kind, 2, "string")
813 AceDB:argCheck(defaults, 3, "table")
814 end
815 if kind ~= "char" and kind ~= "class" and kind ~= "profile" and kind ~= "account" and kind ~= "realm" and kind ~= "faction" then
816 AceDB:error("Bad argument #%d to `RegisterDefaults' (\"char\", \"class\", \"profile\", \"account\", \"realm\", or \"faction\" expected, got %q)", a3 and 3 or 2, kind)
817 end
818 if type(self.db) ~= "table" or type(self.db.name) ~= "string" then
819 AceDB:error("Cannot call \"RegisterDefaults\" unless \"RegisterDB\" has been previously called.")
820 end
821 local db
822 if name then
823 local namespace = self:AcquireDBNamespace(name)
824 if namespace.defaults and namespace.defaults[kind] then
825 AceDB:error("\"RegisterDefaults\" has already been called for %q::%q.", name, kind)
826 end
827 db = namespace
828 else
829 if self.db.defaults and self.db.defaults[kind] then
830 AceDB:error("\"RegisterDefaults\" has already been called for %q.", kind)
831 end
832 db = self.db
833 end
834 if not db.defaults then
835 rawset(db, 'defaults', {})
836 end
837 db.defaults[kind] = defaults
838 if rawget(db, kind) then
839 inheritDefaults(db[kind], defaults)
840 end
841 end
842
843 function AceDB:ResetDB(kind)
844 AceDB:argCheck(kind, 2, "nil", "string")
845 if not self.db or not self.db.raw then
846 AceDB:error("Cannot call \"ResetDB\" before \"RegisterDB\" has been called and before \"ADDON_LOADED\" has been fired.")
847 end
848 local db = self.db
849 if kind == nil then
850 if db.charName then
851 _G[db.charName] = nil
852 end
853 _G[db.name] = nil
854 rawset(db, 'raw', nil)
855 AceDB.InitializeDB(self)
856 if db.namespaces then
857 for name,v in pairs(db.namespaces) do
858 rawset(v, 'account', nil)
859 rawset(v, 'char', nil)
860 rawset(v, 'class', nil)
861 rawset(v, 'profile', nil)
862 rawset(v, 'realm', nil)
863 rawset(v, 'faction', nil)
864 end
865 end
866 elseif kind == "account" then
867 db.raw.account = nil
868 rawset(db, 'account', nil)
869 if db.namespaces then
870 for name,v in pairs(db.namespaces) do
871 rawset(v, 'account', nil)
872 end
873 end
874 elseif kind == "char" then
875 if db.charName then
876 _G[db.charName] = nil
877 else
878 if db.raw.chars then
879 db.raw.chars[charID] = nil
880 end
881 if db.raw.namespaces then
882 for name,v in pairs(db.raw.namespaces) do
883 if v.chars then
884 v.chars[charID] = nil
885 end
886 end
887 end
888 end
889 rawset(db, 'char', nil)
890 if db.namespaces then
891 for name,v in pairs(db.namespaces) do
892 rawset(v, 'char', nil)
893 end
894 end
895 elseif kind == "realm" then
896 if db.raw.realms then
897 db.raw.realms[realmID] = nil
898 end
899 rawset(db, 'realm', nil)
900 if db.raw.namespaces then
901 for name,v in pairs(db.raw.namespaces) do
902 if v.realms then
903 v.realms[realmID] = nil
904 end
905 end
906 end
907 if db.namespaces then
908 for name,v in pairs(db.namespaces) do
909 rawset(v, 'realm', nil)
910 end
911 end
912 elseif kind == "faction" then
913 if db.raw.factions then
914 db.raw.factions[faction] = nil
915 end
916 rawset(db, 'faction', nil)
917 if db.raw.namespaces then
918 for name,v in pairs(db.raw.namespaces) do
919 if v.factions then
920 v.factions[faction] = nil
921 end
922 end
923 end
924 if db.namespaces then
925 for name,v in pairs(db.namespaces) do
926 rawset(v, 'faction', nil)
927 end
928 end
929 elseif kind == "class" then
930 if db.raw.realms then
931 db.raw.realms[classID] = nil
932 end
933 rawset(db, 'class', nil)
934 if db.raw.namespaces then
935 for name,v in pairs(db.raw.namespaces) do
936 if v.classes then
937 v.classes[classID] = nil
938 end
939 end
940 end
941 if db.namespaces then
942 for name,v in pairs(db.namespaces) do
943 rawset(v, 'class', nil)
944 end
945 end
946 elseif kind == "profile" then
947 local id = db.raw.currentProfile and db.raw.currentProfile[charID] or "Default"
948 if id == "char" then
949 id = "char/" .. charID
950 elseif id == "class" then
951 id = "class/" .. classID
952 elseif id == "realm" then
953 id = "realm/" .. realmID
954 end
955 if db.raw.profiles then
956 db.raw.profiles[id] = nil
957 end
958 rawset(db, 'profile', nil)
959 if db.raw.namespaces then
960 for name,v in pairs(db.raw.namespaces) do
961 if v.profiles then
962 v.profiles[id] = nil
963 end
964 end
965 end
966 if db.namespaces then
967 for name,v in pairs(db.namespaces) do
968 rawset(v, 'profile', nil)
969 end
970 end
971 end
972 end
973
974 local function cleanDefaults(t, defaults)
975 if defaults then
976 for k,v in pairs(defaults) do
977 if k == "*" then
978 if type(v) == "table" then
979 for k in pairs(t) do
980 if (defaults[k] == nil or k == "*") and type(t[k]) == "table" then
981 if cleanDefaults(t[k], v) then
982 t[k] = nil
983 end
984 end
985 end
986 else
987 for k in pairs(t) do
988 if (defaults[k] == nil or k == "*") and t[k] == v then
989 t[k] = nil
990 end
991 end
992 end
993 else
994 if type(v) == "table" then
995 if type(t[k]) == "table" then
996 if cleanDefaults(t[k], v) then
997 t[k] = nil
998 end
999 end
1000 elseif t[k] == v then
1001 t[k] = nil
1002 end
1003 end
1004 end
1005 end
1006 return t and not next(t)
1007 end
1008
1009 function AceDB:GetProfile()
1010 if not self.db or not self.db.raw then
1011 return nil
1012 end
1013 if not self.db.raw.currentProfile then
1014 self.db.raw.currentProfile = {}
1015 end
1016 if not self.db.raw.currentProfile[charID] then
1017 self.db.raw.currentProfile[charID] = "Default"
1018 end
1019 local profile = self.db.raw.currentProfile[charID]
1020 if profile == "char" then
1021 return "char", "char/" .. charID
1022 elseif profile == "class" then
1023 return "class", "class/" .. classID
1024 elseif profile == "realm" then
1025 return "realm", "realm/" .. realmID
1026 end
1027 return profile, profile
1028 end
1029
1030 local function copyTable(to, from)
1031 setmetatable(to, nil)
1032 for k,v in pairs(from) do
1033 if type(k) == "table" then
1034 k = copyTable({}, k)
1035 end
1036 if type(v) == "table" then
1037 v = copyTable({}, v)
1038 end
1039 to[k] = v
1040 end
1041 setmetatable(to, from)
1042 return to
1043 end
1044
1045 function AceDB:SetProfile(name)
1046 AceDB:argCheck(name, 2, "string")
1047 if not self.db or not self.db.raw then
1048 AceDB:error("Cannot call \"SetProfile\" before \"RegisterDB\" has been called and before \"ADDON_LOADED\" has been fired.")
1049 end
1050 local db = self.db
1051 local lowerName = string.lower(name)
1052 if string.sub(lowerName, 1, 5) == "char/" or string.sub(lowerName, 1, 6) == "realm/" or string.sub(lowerName, 1, 6) == "class/" then
1053 if string.sub(lowerName, 1, 5) == "char/" then
1054 name = "char"
1055 else
1056 name = string.sub(lowerName, 1, 5)
1057 end
1058 lowerName = string.lower(name)
1059 end
1060 local oldName = db.raw.currentProfile[charID]
1061 if string.lower(oldName) == string.lower(name) then
1062 return
1063 end
1064 local oldProfileData = db.profile
1065 local realName = name
1066 if lowerName == "char" then
1067 realName = name .. "/" .. charID
1068 elseif lowerName == "realm" then
1069 realName = name .. "/" .. realmID
1070 elseif lowerName == "class" then
1071 realName = name .. "/" .. classID
1072 end
1073 local current = self.class
1074 while current and current ~= AceOO.Class do
1075 if current.mixins then
1076 for mixin in pairs(current.mixins) do
1077 if type(mixin.OnEmbedProfileDisable) == "function" then
1078 safecall(mixin.OnEmbedProfileDisable, mixin, self, realName)
1079 end
1080 end
1081 end
1082 current = current.super
1083 end
1084 if type(self.OnProfileDisable) == "function" then
1085 safecall(self.OnProfileDisable, self, realName)
1086 end
1087 local active = self:IsActive()
1088 db.raw.currentProfile[charID] = name
1089 rawset(db, 'profile', nil)
1090 if db.namespaces then
1091 for k,v in pairs(db.namespaces) do
1092 rawset(v, 'profile', nil)
1093 end
1094 end
1095 local current = self.class
1096 while current and current ~= AceOO.Class do
1097 if current.mixins then
1098 for mixin in pairs(current.mixins) do
1099 if type(mixin.OnEmbedProfileEnable) == "function" then
1100 safecall(mixin.OnEmbedProfileEnable, mixin, self, oldName, oldProfileData)
1101 end
1102 end
1103 end
1104 current = current.super
1105 end
1106 if type(self.OnProfileEnable) == "function" then
1107 safecall(self.OnProfileEnable, self, oldName, oldProfileData)
1108 end
1109 if cleanDefaults(oldProfileData, db.defaults and db.defaults.profile) then
1110 db.raw.profiles[oldName] = nil
1111 if not next(db.raw.profiles) then
1112 db.raw.profiles = nil
1113 end
1114 end
1115 local newactive = self:IsActive()
1116 if active ~= newactive then
1117 if AceOO.inherits(self, "AceAddon-2.0") then
1118 local AceAddon = AceLibrary("AceAddon-2.0")
1119 if not AceAddon.addonsStarted[self] then
1120 return
1121 end
1122 end
1123 if newactive then
1124 local current = self.class
1125 while current and current ~= AceOO.Class do
1126 if current.mixins then
1127 for mixin in pairs(current.mixins) do
1128 if type(mixin.OnEmbedEnable) == "function" then
1129 safecall(mixin.OnEmbedEnable, mixin, self)
1130 end
1131 end
1132 end
1133 current = current.super
1134 end
1135 if type(self.OnEnable) == "function" then
1136 safecall(self.OnEnable, self)
1137 end
1138 if AceEvent then
1139 AceEvent:TriggerEvent("Ace2_AddonEnabled", self)
1140 end
1141 else
1142 local current = self.class
1143 while current and current ~= AceOO.Class do
1144 if current.mixins then
1145 for mixin in pairs(current.mixins) do
1146 if type(mixin.OnEmbedDisable) == "function" then
1147 safecall(mixin.OnEmbedDisable, mixin, self)
1148 end
1149 end
1150 end
1151 current = current.super
1152 end
1153 if type(self.OnDisable) == "function" then
1154 safecall(self.OnDisable, self)
1155 end
1156 if AceEvent then
1157 AceEvent:TriggerEvent("Ace2_AddonDisabled", self)
1158 end
1159 end
1160 end
1161 if self['acedb-profile-list'] then
1162 RecalculateAceDBProfileList(self)
1163 end
1164 if self['acedb-profile-copylist'] then
1165 RecalculateAceDBCopyFromList(self)
1166 end
1167 if Dewdrop then
1168 Dewdrop:Refresh(1)
1169 Dewdrop:Refresh(2)
1170 Dewdrop:Refresh(3)
1171 Dewdrop:Refresh(4)
1172 Dewdrop:Refresh(5)
1173 end
1174 end
1175
1176 function AceDB:CopyProfileFrom(copyFrom)
1177 AceDB:argCheck(copyFrom, 2, "string")
1178 if not self.db or not self.db.raw then
1179 AceDB:error("Cannot call \"CopyProfileFrom\" before \"RegisterDB\" has been called and before \"ADDON_LOADED\" has been fired.")
1180 end
1181 local db = self.db
1182 local lowerCopyFrom = string.lower(copyFrom)
1183 if not db.raw.profiles or not db.raw.profiles[copyFrom] then
1184 local good = false
1185 if db.raw.namespaces then
1186 for _,n in pairs(db.raw.namespaces) do
1187 if n.profiles and n.profiles[copyFrom] then
1188 good = true
1189 break
1190 end
1191 end
1192 end
1193 if not good then
1194 AceDB:error("Cannot copy from profile %q, it does not exist.", copyFrom)
1195 end
1196 end
1197 local currentProfile = db.raw.currentProfile[charID]
1198 if string.lower(currentProfile) == lowerCopyFrom then
1199 AceDB:error("Cannot copy from profile %q, it is currently in use.", copyFrom)
1200 end
1201 local oldProfileData = db.profile
1202 local current = self.class
1203 while current and current ~= AceOO.Class do
1204 if current.mixins then
1205 for mixin in pairs(current.mixins) do
1206 if type(mixin.OnEmbedProfileDisable) == "function" then
1207 safecall(mixin.OnEmbedProfileDisable, mixin, self, currentProfile)
1208 end
1209 end
1210 end
1211 current = current.super
1212 end
1213 if type(self.OnProfileDisable) == "function" then
1214 safecall(self.OnProfileDisable, self, realName)
1215 end
1216 local active = self:IsActive()
1217 for k,v in pairs(db.profile) do
1218 db.profile[k] = nil
1219 end
1220 if db.raw.profiles[copyFrom] then
1221 copyTable(db.profile, db.raw.profiles[copyFrom])
1222 end
1223 inheritDefaults(db.profile, db.defaults and db.defaults.profile)
1224 if db.namespaces then
1225 for l,u in pairs(db.namespaces) do
1226 for k,v in pairs(u.profile) do
1227 u.profile[k] = nil
1228 end
1229 if db.raw.namespaces[l].profiles[copyFrom] then
1230 copyTable(u.profile, db.raw.namespaces[l].profiles[copyFrom])
1231 end
1232 inheritDefaults(u.profile, u.defaults and u.defaults.profile)
1233 end
1234 end
1235 local current = self.class
1236 while current and current ~= AceOO.Class do
1237 if current.mixins then
1238 for mixin in pairs(current.mixins) do
1239 if type(mixin.OnEmbedProfileEnable) == "function" then
1240 safecall(mixin.OnEmbedProfileEnable, mixin, self, copyFrom, oldProfileData, copyFrom)
1241 end
1242 end
1243 end
1244 current = current.super
1245 end
1246 if type(self.OnProfileEnable) == "function" then
1247 safecall(self.OnProfileEnable, self, copyFrom, oldProfileData, copyFrom)
1248 end
1249 local newactive = self:IsActive()
1250 if active ~= newactive then
1251 if AceOO.inherits(self, "AceAddon-2.0") then
1252 local AceAddon = AceLibrary("AceAddon-2.0")
1253 if not AceAddon.addonsStarted[self] then
1254 return
1255 end
1256 end
1257 if newactive then
1258 local current = self.class
1259 while current and current ~= AceOO.Class do
1260 if current.mixins then
1261 for mixin in pairs(current.mixins) do
1262 if type(mixin.OnEmbedEnable) == "function" then
1263 safecall(mixin.OnEmbedEnable, mixin, self)
1264 end
1265 end
1266 end
1267 current = current.super
1268 end
1269 if type(self.OnEnable) == "function" then
1270 safecall(self.OnEnable, self)
1271 end
1272 if AceEvent then
1273 AceEvent:TriggerEvent("Ace2_AddonEnabled", self)
1274 end
1275 else
1276 local current = self.class
1277 while current and current ~= AceOO.Class do
1278 if current.mixins then
1279 for mixin in pairs(current.mixins) do
1280 if type(mixin.OnEmbedDisable) == "function" then
1281 safecall(mixin.OnEmbedDisable, mixin, self)
1282 end
1283 end
1284 end
1285 current = current.super
1286 end
1287 if type(self.OnDisable) == "function" then
1288 safecall(self.OnDisable, self)
1289 end
1290 if AceEvent then
1291 AceEvent:TriggerEvent("Ace2_AddonDisabled", self)
1292 end
1293 end
1294 end
1295 if self['acedb-profile-list'] then
1296 RecalculateAceDBProfileList(self)
1297 end
1298 if self['acedb-profile-copylist'] then
1299 RecalculateAceDBCopyFromList(self)
1300 end
1301 if Dewdrop then
1302 Dewdrop:Refresh(1)
1303 Dewdrop:Refresh(2)
1304 Dewdrop:Refresh(3)
1305 Dewdrop:Refresh(4)
1306 Dewdrop:Refresh(5)
1307 end
1308 end
1309
1310 function AceDB:IsActive()
1311 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]]
1312 end
1313
1314 function AceDB:ToggleActive(state)
1315 AceDB:argCheck(state, 2, "boolean", "nil")
1316 if not self.db or not self.db.raw then
1317 AceDB:error("Cannot call \"ToggleActive\" before \"RegisterDB\" has been called and before \"ADDON_LOADED\" has been fired.")
1318 end
1319 local db = self.db
1320 if not db.raw.disabled then
1321 db.raw.disabled = setmetatable({}, caseInsensitive_mt)
1322 end
1323 local profile = db.raw.currentProfile[charID]
1324 local disable
1325 if state == nil then
1326 disable = not db.raw.disabled[profile]
1327 else
1328 disable = not state
1329 if disable == db.raw.disabled[profile] then
1330 return
1331 end
1332 end
1333 db.raw.disabled[profile] = disable or nil
1334 if AceOO.inherits(self, "AceAddon-2.0") then
1335 local AceAddon = AceLibrary("AceAddon-2.0")
1336 if not AceAddon.addonsStarted[self] then
1337 return
1338 end
1339 end
1340 if not disable then
1341 local current = self.class
1342 while current and current ~= AceOO.Class do
1343 if current.mixins then
1344 for mixin in pairs(current.mixins) do
1345 if type(mixin.OnEmbedEnable) == "function" then
1346 safecall(mixin.OnEmbedEnable, mixin, self)
1347 end
1348 end
1349 end
1350 current = current.super
1351 end
1352 if type(self.OnEnable) == "function" then
1353 safecall(self.OnEnable, self)
1354 end
1355 if AceEvent then
1356 AceEvent:TriggerEvent("Ace2_AddonEnabled", self)
1357 end
1358 else
1359 local current = self.class
1360 while current and current ~= AceOO.Class do
1361 if current.mixins then
1362 for mixin in pairs(current.mixins) do
1363 if type(mixin.OnEmbedDisable) == "function" then
1364 safecall(mixin.OnEmbedDisable, mixin, self)
1365 end
1366 end
1367 end
1368 current = current.super
1369 end
1370 if type(self.OnDisable) == "function" then
1371 safecall(self.OnDisable, self)
1372 end
1373 if AceEvent then
1374 AceEvent:TriggerEvent("Ace2_AddonDisabled", self)
1375 end
1376 end
1377 return not disable
1378 end
1379
1380 function AceDB:embed(target)
1381 self.super.embed(self, target)
1382 if not AceEvent then
1383 AceDB:error(MAJOR_VERSION .. " requires AceEvent-2.0")
1384 end
1385 end
1386
1387 function AceDB:ADDON_LOADED(name)
1388 AceDB.addonsLoaded[name] = true
1389 for addon, addonName in pairs(AceDB.addonsToBeInitialized) do
1390 if name == addonName then
1391 AceDB.InitializeDB(addon, name)
1392 AceDB.addonsToBeInitialized[addon] = nil
1393 end
1394 end
1395 end
1396
1397 function AceDB:PLAYER_LOGOUT()
1398 for addon in pairs(AceDB.registry) do
1399 local db = addon.db
1400 if db then
1401 setmetatable(db, nil)
1402 CrawlForSerialization(db.raw)
1403 if type(_G[db.charName]) == "table" then
1404 CrawlForSerialization(_G[db.charName])
1405 end
1406 if db.char and cleanDefaults(db.char, db.defaults and db.defaults.char) then
1407 if db.charName and _G[db.charName] and _G[db.charName].global == db.char then
1408 _G[db.charName].global = nil
1409 if not next(_G[db.charName]) then
1410 _G[db.charName] = nil
1411 end
1412 else
1413 if db.raw.chars then
1414 db.raw.chars[charID] = nil
1415 if not next(db.raw.chars) then
1416 db.raw.chars = nil
1417 end
1418 end
1419 end
1420 end
1421 if db.realm and cleanDefaults(db.realm, db.defaults and db.defaults.realm) then
1422 if db.raw.realms then
1423 db.raw.realms[realmID] = nil
1424 if not next(db.raw.realms) then
1425 db.raw.realms = nil
1426 end
1427 end
1428 end
1429 if db.faction and cleanDefaults(db.faction, db.defaults and db.defaults.faction) then
1430 if db.raw.factions then
1431 db.raw.factions[faction] = nil
1432 if not next(db.raw.factions) then
1433 db.raw.factions = nil
1434 end
1435 end
1436 end
1437 if db.class and cleanDefaults(db.class, db.defaults and db.defaults.class) then
1438 if db.raw.classes then
1439 db.raw.classes[classID] = nil
1440 if not next(db.raw.classes) then
1441 db.raw.classes = nil
1442 end
1443 end
1444 end
1445 if db.account and cleanDefaults(db.account, db.defaults and db.defaults.account) then
1446 db.raw.account = nil
1447 end
1448 if db.profile and cleanDefaults(db.profile, db.defaults and db.defaults.profile) then
1449 if db.raw.profiles then
1450 db.raw.profiles[db.raw.currentProfile and db.raw.currentProfile[charID] or "Default"] = nil
1451 if not next(db.raw.profiles) then
1452 db.raw.profiles = nil
1453 end
1454 end
1455 end
1456 if db.namespaces and db.raw.namespaces then
1457 for name,v in pairs(db.namespaces) do
1458 if db.raw.namespaces[name] then
1459 setmetatable(v, nil)
1460 if v.char and cleanDefaults(v.char, v.defaults and v.defaults.char) then
1461 if db.charName and _G[db.charName] and _G[db.charName].namespaces and _G[db.charName].namespaces[name] == v then
1462 _G[db.charName].namespaces[name] = nil
1463 if not next(_G[db.charName].namespaces) then
1464 _G[db.charName].namespaces = nil
1465 if not next(_G[db.charName]) then
1466 _G[db.charName] = nil
1467 end
1468 end
1469 else
1470 if db.raw.namespaces[name].chars then
1471 db.raw.namespaces[name].chars[charID] = nil
1472 if not next(db.raw.namespaces[name].chars) then
1473 db.raw.namespaces[name].chars = nil
1474 end
1475 end
1476 end
1477 end
1478 if v.realm and cleanDefaults(v.realm, v.defaults and v.defaults.realm) then
1479 if db.raw.namespaces[name].realms then
1480 db.raw.namespaces[name].realms[realmID] = nil
1481 if not next(db.raw.namespaces[name].realms) then
1482 db.raw.namespaces[name].realms = nil
1483 end
1484 end
1485 end
1486 if v.faction and cleanDefaults(v.faction, v.defaults and v.defaults.faction) then
1487 if db.raw.namespaces[name].factions then
1488 db.raw.namespaces[name].factions[faction] = nil
1489 if not next(db.raw.namespaces[name].factions) then
1490 db.raw.namespaces[name].factions = nil
1491 end
1492 end
1493 end
1494 if v.class and cleanDefaults(v.class, v.defaults and v.defaults.class) then
1495 if db.raw.namespaces[name].classes then
1496 db.raw.namespaces[name].classes[classID] = nil
1497 if not next(db.raw.namespaces[name].classes) then
1498 db.raw.namespaces[name].classes = nil
1499 end
1500 end
1501 end
1502 if v.account and cleanDefaults(v.account, v.defaults and v.defaults.account) then
1503 db.raw.namespaces[name].account = nil
1504 end
1505 if v.profile and cleanDefaults(v.profile, v.defaults and v.defaults.profile) then
1506 if db.raw.namespaces[name].profiles then
1507 db.raw.namespaces[name].profiles[db.raw.currentProfile and db.raw.currentProfile[charID] or "Default"] = nil
1508 if not next(db.raw.namespaces[name].profiles) then
1509 db.raw.namespaces[name].profiles = nil
1510 end
1511 end
1512 end
1513 if not next(db.raw.namespaces[name]) then
1514 db.raw.namespaces[name] = nil
1515 end
1516 end
1517 end
1518 if not next(db.raw.namespaces) then
1519 db.raw.namespaces = nil
1520 end
1521 end
1522 if db.raw.disabled and not next(db.raw.disabled) then
1523 db.raw.disabled = nil
1524 end
1525 if db.raw.currentProfile then
1526 for k,v in pairs(db.raw.currentProfile) do
1527 if string.lower(v) == "default" then
1528 db.raw.currentProfile[k] = nil
1529 end
1530 end
1531 if not next(db.raw.currentProfile) then
1532 db.raw.currentProfile = nil
1533 end
1534 end
1535 if _G[db.name] and not next(_G[db.name]) then
1536 _G[db.name] = nil
1537 end
1538 end
1539 end
1540 end
1541
1542 function AceDB:AcquireDBNamespace(name)
1543 AceDB:argCheck(name, 2, "string")
1544 local db = self.db
1545 if not db then
1546 AceDB:error("Cannot call `AcquireDBNamespace' before `RegisterDB' has been called.", 2)
1547 end
1548 if not db.namespaces then
1549 rawset(db, 'namespaces', {})
1550 end
1551 if not db.namespaces[name] then
1552 local namespace = {}
1553 db.namespaces[name] = namespace
1554 namespace.db = db
1555 namespace.name = name
1556 setmetatable(namespace, namespace_mt)
1557 end
1558 return db.namespaces[name]
1559 end
1560
1561 function AceDB:GetAceOptionsDataTable(target)
1562 if not target['acedb-profile-list'] then
1563 target['acedb-profile-list'] = setmetatable({}, caseInsensitive_mt)
1564 RecalculateAceDBProfileList(target)
1565 end
1566 if not target['acedb-profile-copylist'] then
1567 target['acedb-profile-copylist'] = setmetatable({}, caseInsensitive_mt)
1568 RecalculateAceDBCopyFromList(target)
1569 end
1570 return {
1571 standby = {
1572 cmdName = STATE,
1573 guiName = ENABLED,
1574 name = ACTIVE,
1575 desc = TOGGLE_ACTIVE,
1576 type = "toggle",
1577 get = "IsActive",
1578 set = "ToggleActive",
1579 map = MAP_ACTIVESUSPENDED,
1580 order = -3,
1581 },
1582 profile = {
1583 type = 'group',
1584 name = PROFILE,
1585 desc = SET_PROFILE,
1586 order = -3.5,
1587 get = "GetProfile",
1588 args = {
1589 choose = {
1590 guiName = CHOOSE_PROFILE_GUI,
1591 cmdName = PROFILE,
1592 desc = CHOOSE_PROFILE_DESC,
1593 type = 'text',
1594 get = "GetProfile",
1595 set = "SetProfile",
1596 validate = target['acedb-profile-list']
1597 },
1598 copy = {
1599 guiName = COPY_PROFILE_GUI,
1600 cmdName = PROFILE,
1601 desc = COPY_PROFILE_DESC,
1602 type = 'text',
1603 get = false,
1604 set = "CopyProfileFrom",
1605 validate = target['acedb-profile-copylist'],
1606 disabled = function()
1607 return not next(target['acedb-profile-copylist'])
1608 end,
1609 },
1610 other = {
1611 guiName = OTHER_PROFILE_GUI,
1612 cmdName = PROFILE,
1613 desc = OTHER_PROFILE_DESC,
1614 usage = OTHER_PROFILE_USAGE,
1615 type = 'text',
1616 get = "GetProfile",
1617 set = "SetProfile",
1618 }
1619 }
1620 },
1621 }
1622 end
1623
1624 local function activate(self, oldLib, oldDeactivate)
1625 AceDB = self
1626 AceEvent = AceLibrary:HasInstance("AceEvent-2.0") and AceLibrary("AceEvent-2.0")
1627
1628 self.addonsToBeInitialized = oldLib and oldLib.addonsToBeInitialized or {}
1629 self.addonsLoaded = oldLib and oldLib.addonsLoaded or {}
1630 self.registry = oldLib and oldLib.registry or {}
1631
1632 self:activate(oldLib, oldDeactivate)
1633
1634 for t in pairs(self.embedList) do
1635 if t.db then
1636 rawset(t.db, 'char', nil)
1637 rawset(t.db, 'realm', nil)
1638 rawset(t.db, 'class', nil)
1639 rawset(t.db, 'account', nil)
1640 rawset(t.db, 'faction', nil)
1641 rawset(t.db, 'profile', nil)
1642 setmetatable(t.db, db_mt)
1643 end
1644 end
1645
1646 if oldLib then
1647 oldDeactivate(oldLib)
1648 end
1649 end
1650
1651 local function external(self, major, instance)
1652 if major == "AceEvent-2.0" then
1653 AceEvent = instance
1654
1655 AceEvent:embed(self)
1656
1657 self:RegisterEvent("ADDON_LOADED")
1658 self:RegisterEvent("PLAYER_LOGOUT")
1659 elseif major == "Dewdrop-2.0" then
1660 Dewdrop = instance
1661 end
1662 end
1663
1664 AceLibrary:Register(AceDB, MAJOR_VERSION, MINOR_VERSION, activate, nil, external)
1665 AceDB = AceLibrary(MAJOR_VERSION)