Mercurial > wow > reaction
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) |