📄 dongle.lua
字号:
tbl[self] = nil if not next(tbl) then messages[msg] = nil end endendfunction Dongle:UnregisterAllMessages() argcheck(self, 1, "table") for msg,tbl in pairs(messages) do tbl[self] = nil if not next(tbl) then messages[msg] = nil end endendfunction Dongle:TriggerMessage(msg, ...) argcheck(self, 1, "table") argcheck(msg, 2, "string") local msgTbl = messages[msg] if not msgTbl then return end for obj,func in pairs(msgTbl) do if type(func) == "string" then if type(obj[func]) == "function" then safecall(obj[func], obj, msg, ...) end else safecall(func, msg, ...) end endendfunction Dongle:IsMessageRegistered(msg) argcheck(self, 1, "table") argcheck(msg, 2, "string") local tbl = messages[msg] return tbl[self]end--[[------------------------------------------------------------------------- Debug and Print utility functions---------------------------------------------------------------------------]]function Dongle:EnableDebug(level, frame) local reg = lookup[self] assert(3, reg, string.format(L["MUST_CALLFROM_REGISTERED"], "EnableDebug")) argcheck(level, 2, "number", "nil") argcheck(frame, 3, "table", "nil") assert(3, type(frame) == "nil" or type(frame.AddMessage) == "function", L["ADDMESSAGE_REQUIRED"]) reg.debugFrame = frame or ChatFrame1 reg.debugLevel = levelendfunction Dongle:IsDebugEnabled() local reg = lookup[self] assert(3, reg, string.format(L["MUST_CALLFROM_REGISTERED"], "EnableDebug")) return reg.debugLevel, reg.debugFrameendlocal function argsToStrings(a1, ...) if select("#", ...) > 0 then return tostring(a1), argsToStrings(...) else return tostring(a1) endendlocal function printHelp(obj, method, header, frame, msg, ...) local reg = lookup[obj] assert(4, reg, string.format(L["MUST_CALLFROM_REGISTERED"], method)) local name = reg.name if header then msg = "|cFF33FF99"..name.."|r: "..tostring(msg) end if select("#", ...) > 0 then msg = string.join(", ", msg, argsToStrings(...)) end frame:AddMessage(msg)endlocal function printFHelp(obj, method, header, frame, msg, ...) local reg = lookup[obj] assert(4, reg, string.format(L["MUST_CALLFROM_REGISTERED"], method)) local name = reg.name local success,txt if header then msg = "|cFF33FF99%s|r: " .. msg success,txt = pcall(string.format, msg, name, ...) else success,txt = pcall(string.format, msg, ...) end if success then frame:AddMessage(txt) else error(string.gsub(txt, "'%?'", string.format("'%s'", method)), 3) endendfunction Dongle:Print(msg, ...) local reg = lookup[self] assert(1, reg, string.format(L["MUST_CALLFROM_REGISTERED"], "Print")) argcheck(msg, 2, "number", "string", "boolean", "table", "function", "thread", "userdata") return printHelp(self, "Print", true, DEFAULT_CHAT_FRAME, msg, ...)endfunction Dongle:PrintF(msg, ...) local reg = lookup[self] assert(1, reg, string.format(L["MUST_CALLFROM_REGISTERED"], "PrintF")) argcheck(msg, 2, "number", "string", "boolean", "table", "function", "thread", "userdata") return printFHelp(self, "PrintF", true, DEFAULT_CHAT_FRAME, msg, ...)endfunction Dongle:Echo(msg, ...) local reg = lookup[self] assert(1, reg, string.format(L["MUST_CALLFROM_REGISTERED"], "Echo")) argcheck(msg, 2, "number", "string", "boolean", "table", "function", "thread", "userdata") return printHelp(self, "Echo", false, DEFAULT_CHAT_FRAME, msg, ...)endfunction Dongle:EchoF(msg, ...) local reg = lookup[self] assert(1, reg, string.format(L["MUST_CALLFROM_REGISTERED"], "EchoF")) argcheck(msg, 2, "number", "string", "boolean", "table", "function", "thread", "userdata") return printFHelp(self, "EchoF", false, DEFAULT_CHAT_FRAME, msg, ...)endfunction Dongle:Debug(level, ...) local reg = lookup[self] assert(3, reg, string.format(L["MUST_CALLFROM_REGISTERED"], "Debug")) argcheck(level, 2, "number") if reg.debugLevel and level <= reg.debugLevel then printHelp(self, "Debug", true, reg.debugFrame, ...) endendfunction Dongle:DebugF(level, ...) local reg = lookup[self] assert(3, reg, string.format(L["MUST_CALLFROM_REGISTERED"], "DebugF")) argcheck(level, 2, "number") if reg.debugLevel and level <= reg.debugLevel then printFHelp(self, "DebugF", true, reg.debugFrame, ...) endend--[[------------------------------------------------------------------------- Database System---------------------------------------------------------------------------]]local dbMethods = { "RegisterDefaults", "SetProfile", "GetProfiles", "DeleteProfile", "CopyProfile", "GetCurrentProfile", "ResetProfile", "ResetDB", "RegisterNamespace",}local function copyTable(src) local dest = {} for k,v in pairs(src) do if type(k) == "table" then k = copyTable(k) end if type(v) == "table" then v = copyTable(v) end dest[k] = v end return destendlocal function copyDefaults(dest, src, force) for k,v in pairs(src) do if k == "*" then if type(v) == "table" then -- Values are tables, need some magic here local mt = { __cache = {}, __index = function(t,k) local mt = getmetatable(dest) local cache = rawget(mt, "__cache") local tbl = rawget(cache, k) if not tbl then local parent = t local parentkey = k tbl = copyTable(v) rawset(cache, k, tbl) local mt = getmetatable(tbl) if not mt then mt = {} setmetatable(tbl, mt) end local newindex = function(t,k,v) rawset(parent, parentkey, t) rawset(t, k, v) end rawset(mt, "__newindex", newindex) end return tbl end, } setmetatable(dest, mt) -- Now need to set the metatable on any child tables for dkey,dval in pairs(dest) do copyDefaults(dval, v) end else -- Values are not tables, so this is just a simple return local mt = {__index = function() return v end} setmetatable(dest, mt) end elseif type(v) == "table" then if not dest[k] then dest[k] = {} end copyDefaults(dest[k], v, force) else if (dest[k] == nil) or force then dest[k] = v end end endendlocal function removeDefaults(db, defaults) if not db then return end for k,v in pairs(defaults) do if k == "*" and type(v) == "table" then -- check for any defaults that have been changed local mt = getmetatable(db) local cache = rawget(mt, "__cache") for cacheKey,cacheValue in pairs(cache) do removeDefaults(cacheValue, v) if next(cacheValue) ~= nil then -- Something's changed rawset(db, cacheKey, cacheValue) end end -- Now loop through all the actual k,v pairs and remove for key,value in pairs(db) do removeDefaults(value, v) end elseif type(v) == "table" and db[k] then removeDefaults(db[k], v) if not next(db[k]) then db[k] = nil end else if db[k] == defaults[k] then db[k] = nil end end endendlocal function initSection(db, section, svstore, key, defaults) local sv = rawget(db, "sv") local tableCreated if not sv[svstore] then sv[svstore] = {} end if not sv[svstore][key] then sv[svstore][key] = {} tableCreated = true end local tbl = sv[svstore][key] if defaults then copyDefaults(tbl, defaults) end rawset(db, section, tbl) return tableCreated, tblendlocal dbmt = { __index = function(t, section) local keys = rawget(t, "keys") local key = keys[section] if key then local defaultTbl = rawget(t, "defaults") local defaults = defaultTbl and defaultTbl[section] if section == "profile" then local new = initSection(t, section, "profiles", key, defaults) if new then Dongle:TriggerMessage("DONGLE_PROFILE_CREATED", t, rawget(t, "parent"), rawget(t, "sv_name"), key) end elseif section == "profiles" then local sv = rawget(t, "sv") if not sv.profiles then sv.profiles = {} end rawset(t, "profiles", sv.profiles) elseif section == "global" then local sv = rawget(t, "sv") if not sv.global then sv.global = {} end if defaults then copyDefaults(sv.global, defaults) end rawset(t, section, sv.global) else initSection(t, section, section, key, defaults) end end return rawget(t, section) end}local function initdb(parent, name, defaults, defaultProfile, olddb) -- This allows us to use an arbitrary table as base instead of saved variable name local sv if type(name) == "string" then sv = getglobal(name) if not sv then sv = {} setglobal(name, sv) end elseif type(name) == "table" then sv = name end -- Generate the database keys for each section local char = string.format("%s - %s", UnitName("player"), GetRealmName()) local realm = GetRealmName() local class = select(2, UnitClass("player")) local race = select(2, UnitRace("player")) local faction = UnitFactionGroup("player") local factionrealm = string.format("%s - %s", faction, realm) -- Make a container for profile keys if not sv.profileKeys then sv.profileKeys = {} end -- Try to get the profile selected from the char db local profileKey = sv.profileKeys[char] or defaultProfile or char sv.profileKeys[char] = profileKey local keyTbl= { ["char"] = char, ["realm"] = realm, ["class"] = class, ["race"] = race, ["faction"] = faction, ["factionrealm"] = factionrealm, ["global"] = true, ["profile"] = profileKey, ["profiles"] = true, -- Don't create until we need } -- If we've been passed an old database, clear it out if olddb then for k,v in pairs(olddb) do olddb[k] = nil end end -- Give this database the metatable so it initializes dynamically local db = setmetatable(olddb or {}, dbmt) -- Copy methods locally for idx,method in pairs(dbMethods) do db[method] = Dongle[method] end -- Set some properties in the object we're returning db.profiles = sv.profiles db.keys = keyTbl db.sv = sv db.sv_name = name db.defaults = defaults db.parent = parent databases[db] = true return dbendfunction Dongle:InitializeDB(name, defaults, defaultProfile) local reg = lookup[self] assert(3, reg, string.format(L["MUST_CALLFROM_REGISTERED"], "InitializeDB")) argcheck(name, 2, "string", "table") argcheck(defaults, 3, "table", "nil") argcheck(defaultProfile, 4, "string", "nil") return initdb(self, name, defaults, defaultProfile)end-- This function operates on a Dongle DB objectfunction Dongle.RegisterDefaults(db, defaults) assert(3, databases[db], string.format(L["MUST_CALLFROM_DBOBJECT"], "RegisterDefaults")) assert(3, db.defaults == nil, L["REPLACE_DEFAUTS"]) argcheck(defaults, 2, "table") for section,key in pairs(db.keys) do if defaults[section] and rawget(db, section) then copyDefaults(db[section], defaults[section]) end end db.defaults = defaultsendfunction Dongle:ClearDBDefaults() for db in pairs(databases) do local defaults = db.defaults local sv = db.sv if db and defaults then for section,key in pairs(db.keys) do if defaults[section] and rawget(db, section) then removeDefaults(db[section], defaults[section]) end end for section,key in pairs(db.keys) do local tbl = rawget(db, section) if tbl and not next(tbl) then if sv[section] then if type(key) == "string" then sv[section][key] = nil else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -