update LibWho-2.0 (fully working now)

Thank you @Bunny67
This commit is contained in:
Crum
2018-06-23 18:34:07 -05:00
parent 87e43e9a1c
commit 7c112f666f
+164 -196
View File
@@ -6,7 +6,7 @@ if WhoLibByALeX or WhoLib then
-- the WhoLib-1.0 (WhoLibByALeX) or WhoLib (by Malex) is loaded -> fail! -- the WhoLib-1.0 (WhoLibByALeX) or WhoLib (by Malex) is loaded -> fail!
error("an other WhoLib is already running - disable them first!\n") error("an other WhoLib is already running - disable them first!\n")
return return
end -- if end
--- ---
--- check version --- check version
@@ -14,7 +14,6 @@ end -- if
assert(LibStub, "LibWho-2.0 requires LibStub") assert(LibStub, "LibWho-2.0 requires LibStub")
local major_version = 'LibWho-2.0' local major_version = 'LibWho-2.0'
local minor_version = tonumber("154") or 99999 local minor_version = tonumber("154") or 99999
@@ -28,6 +27,11 @@ end
lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib) lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib)
local callbacks = lib.callbacks local callbacks = lib.callbacks
local band = bit.band
local find, format, gsub, len, sub = string.find, string.format, string.gsub, string.len, string.sub
local insert, getn = table.insert, table.getn
local random = math.random
local am = {} local am = {}
local om = getmetatable(lib) local om = getmetatable(lib)
if om then if om then
@@ -46,26 +50,26 @@ local dbg = NOP
if type(lib['hooked']) ~= 'table' then if type(lib['hooked']) ~= 'table' then
lib['hooked'] = {} lib['hooked'] = {}
end -- if end
if type(lib['hook']) ~= 'table' then if type(lib['hook']) ~= 'table' then
lib['hook'] = {} lib['hook'] = {}
end -- if end
if type(lib['events']) ~= 'table' then if type(lib['events']) ~= 'table' then
lib['events'] = {} lib['events'] = {}
end -- if end
if type(lib['embeds']) ~= 'table' then if type(lib['embeds']) ~= 'table' then
lib['embeds'] = {} lib['embeds'] = {}
end -- if end
if type(lib['frame']) ~= 'table' then if type(lib['frame']) ~= 'table' then
lib['frame'] = CreateFrame('Frame', major_version); lib['frame'] = CreateFrame('Frame', major_version)
end -- if end
lib['frame']:Hide() lib['frame']:Hide()
lib.Queue = {[1]={}, [2]={}, [3]={}} lib.Queue = {[1] = {}, [2] = {}, [3] = {}}
lib.WhoInProgress = false lib.WhoInProgress = false
lib.Result = nil lib.Result = nil
lib.Args = nil lib.Args = nil
@@ -97,7 +101,7 @@ else
['console_query'] = 'Result of "/who %s"', ['console_query'] = 'Result of "/who %s"',
['gui_wait'] = '- Please Wait -', ['gui_wait'] = '- Please Wait -',
} }
end -- if end
--- ---
@@ -139,7 +143,7 @@ local queue_quiet = {
lib['WHOLIB_FLAG_ALWAYS_CALLBACK'] = 1 lib['WHOLIB_FLAG_ALWAYS_CALLBACK'] = 1
function lib:Reset() function lib:Reset()
self.Queue = {[1]={}, [2]={}, [3]={}} self.Queue = {[1] = {}, [2] = {}, [3] = {}}
self.Cache = {} self.Cache = {}
self.CacheQueue = {} self.CacheQueue = {}
end end
@@ -170,9 +174,9 @@ function lib.UserInfo(defhandler, name, opts)
local now = time() local now = time()
name = self:CheckArgument(usage, 'name', 'string', name) name = self:CheckArgument(usage, 'name', 'string', name)
if strlen(name) == 0 then return end if len(name) == 0 then return end
if string.find(name, "%-") then --[[dbg("ignoring xrealm: "..name)]] return end if find(name, "%-") then --[[dbg("ignoring xrealm: "..name)]] return end
args.name = self:CapitalizeInitial(name) args.name = self:CapitalizeInitial(name)
opts = self:CheckArgument(usage, 'opts', 'table', opts, {}) opts = self:CheckArgument(usage, 'opts', 'table', opts, {})
@@ -184,23 +188,23 @@ function lib.UserInfo(defhandler, name, opts)
-- now args - copied and verified from opts -- now args - copied and verified from opts
local cachedName = self.Cache[args.name] local cachedName = self.Cache[args.name]
if(cachedName ~= nil)then if cachedName ~= nil then
-- user is in cache -- user is in cache
if(cachedName.valid == true and (args.timeout < 0 or cachedName.last + args.timeout*60 > now))then if cachedName.valid == true and (args.timeout < 0 or cachedName.last + args.timeout*60 > now) then
-- cache is valid and timeout is in range -- cache is valid and timeout is in range
--dbg('Info(' .. args.name ..') returned immedeatly') --dbg('Info('..args.name ..') returned immedeatly')
if(bit.band(args.flags, self.WHOLIB_FLAG_ALWAYS_CALLBACK) ~= 0)then if band(args.flags, self.WHOLIB_FLAG_ALWAYS_CALLBACK) ~= 0 then
self:RaiseCallback(args, cachedName.data) self:RaiseCallback(args, cachedName.data)
return false return false
else else
return self:DupAll(self:ReturnUserInfo(args.name)) return self:DupAll(self:ReturnUserInfo(args.name))
end end
elseif(cachedName.valid == false)then elseif cachedName.valid == false then
-- query is already running (first try) -- query is already running (first try)
if(args.callback ~= nil)then if args.callback ~= nil then
tinsert(cachedName.callback, args) insert(cachedName.callback, args)
end end
--dbg('Info(' .. args.name ..') returned cause it\'s already searching') --dbg('Info('..args.name ..') returned cause it\'s already searching')
return nil return nil
end end
else else
@@ -209,34 +213,34 @@ function lib.UserInfo(defhandler, name, opts)
local cachedName = self.Cache[args.name] local cachedName = self.Cache[args.name]
if(cachedName.inqueue)then if cachedName.inqueue then
-- query is running! -- query is running!
if(args.callback ~= nil)then if args.callback ~= nil then
tinsert(cachedName.callback, args) insert(cachedName.callback, args)
end end
dbg('Info(' .. args.name ..') returned cause it\'s already searching') dbg('Info('..args.name..') returned cause it\'s already searching')
return nil return nil
end end
if (GetLocale() == "ruRU") then -- in ruRU with n- not show information about player in WIM addon if GetLocale() == "ruRU" then -- in ruRU with n- not show information about player in WIM addon
if args.name and strlen(args.name) > 0 then if args.name and len(args.name) > 0 then
local query = 'и-"' .. args.name .. '"' local query = 'и-"'..args.name..'"'
cachedName.inqueue = true cachedName.inqueue = true
if(args.callback ~= nil)then if args.callback ~= nil then
tinsert(cachedName.callback, args) insert(cachedName.callback, args)
end end
self.CacheQueue[query] = args.name self.CacheQueue[query] = args.name
dbg('Info(' .. args.name ..') added to queue') dbg('Info('..args.name ..') added to queue')
self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } ) self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } )
end end
else else
if args.name and strlen(args.name) > 0 then if args.name and len(args.name) > 0 then
local query = 'n-"' .. args.name .. '"' local query = 'n-"'..args.name..'"'
cachedName.inqueue = true cachedName.inqueue = true
if(args.callback ~= nil)then if args.callback ~= nil then
tinsert(cachedName.callback, args) insert(cachedName.callback, args)
end end
self.CacheQueue[query] = args.name self.CacheQueue[query] = args.name
dbg('Info(' .. args.name ..') added to queue') dbg('Info('..args.name..') added to queue')
self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } ) self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } )
end end
end end
@@ -269,7 +273,7 @@ end
-- --
-- self:CheckPreset(usage, 'event', self.events, event) -- self:CheckPreset(usage, 'event', self.events, event)
-- local callback, handler = self:CheckCallback(usage, '', callback, handler, defhandler, true) -- local callback, handler = self:CheckCallback(usage, '', callback, handler, defhandler, true)
-- table.insert(self.events[event], {callback=callback, handler=handler}) -- insert(self.events[event], {callback=callback, handler=handler})
--end --end
-- non-embedded externals -- non-embedded externals
@@ -279,10 +283,10 @@ function lib.Embed(_, handler)
self:CheckArgument(usage, 'handler', 'table', handler) self:CheckArgument(usage, 'handler', 'table', handler)
for _,name in pairs(self.external) do for _, name in pairs(self.external) do
handler[name] = self[name] handler[name] = self[name]
end -- do end
self['embeds'][handler] = true self['embeds'][handler] = true
return handler return handler
end end
@@ -329,8 +333,8 @@ lib['frame']:SetScript("OnUpdate", function()
if lib.Timeout_time <= 0 then if lib.Timeout_time <= 0 then
lib['frame']:Hide() lib['frame']:Hide()
lib:AskWhoNext() lib:AskWhoNext()
end -- if end
end); end)
-- queue scheduler -- queue scheduler
@@ -343,19 +347,19 @@ local INSTANT_QUERY_MIN_INTERVAL = 60 -- only once every 1 min
function lib:UpdateWeights() function lib:UpdateWeights()
local weightsum, sum, count = 0, 0, 0 local weightsum, sum, count = 0, 0, 0
for k,v in pairs(queue_weights) do for k, v in pairs(queue_weights) do
sum = sum + v sum = sum + v
weightsum = weightsum + v * getn(self.Queue[k]) weightsum = weightsum + v * getn(self.Queue[k])
end end
if weightsum == 0 then if weightsum == 0 then
for k,v in pairs(queue_weights) do queue_bounds[k] = v end for k, v in pairs(queue_weights) do queue_bounds[k] = v end
return return
end end
local adjust = sum / weightsum local adjust = sum / weightsum
for k,v in pairs(queue_bounds) do for k, v in pairs(queue_bounds) do
queue_bounds[k] = queue_weights[k] * adjust * getn(self.Queue[k]) queue_bounds[k] = queue_weights[k] * adjust * getn(self.Queue[k])
end end
end end
@@ -374,16 +378,16 @@ function lib:GetNextFromScheduler()
end end
end end
local n,i = math.random(),0 local n,i = random(),0
repeat repeat
i=i+1 i = i + 1
n = n - queue_bounds[i] n = n - queue_bounds[i]
until i >= getn(self.Queue) or n <= 0 until i >= getn(self.Queue) or n <= 0
dbg(string.format("Q=%d, bound=%d", i, queue_bounds[i])) dbg(format("Q=%d, bound=%d", i, queue_bounds[i]))
if getn(self.Queue[i]) > 0 then if getn(self.Queue[i]) > 0 then
dbg(string.format("Q=%d, bound=%d", i, queue_bounds[i])) dbg(format("Q=%d, bound=%d", i, queue_bounds[i]))
return i, self.Queue[i] return i, self.Queue[i]
else else
dbg("Queues empty, waiting") dbg("Queues empty, waiting")
@@ -405,28 +409,28 @@ function lib:AskWhoNext()
dbg("TIMEOUT: "..self.Args.query) dbg("TIMEOUT: "..self.Args.query)
local args = self.Args local args = self.Args
self.Args = nil self.Args = nil
-- if args.info and self.CacheQueue[args.query] ~= nil then if args.info and self.CacheQueue[args.query] ~= nil then
dbg("Requeing "..args.query) dbg("Requeing "..args.query)
tinsert(self.Queue[args.queue], args) insert(self.Queue[args.queue], args)
if args.console_show ~= nil then if args.console_show ~= nil then
DEFAULT_CHAT_FRAME:AddMessage(string.format("Timeout on result of '%s' - retrying...", args.query), 1, 1, 0) DEFAULT_CHAT_FRAME:AddMessage(format("Timeout on result of '%s' - retrying...", args.query),1,1,0)
args.console_show = true args.console_show = true
end end
-- end end
if queryInterval < lib.MaxInterval then if queryInterval < lib.MaxInterval then
queryInterval = queryInterval + 0.5 queryInterval = queryInterval + 0.5
dbg("--Throttling down to 1 who per " .. queryInterval .. "s") dbg("--Throttling down to 1 who per "..queryInterval.."s")
end end
end end
self.WhoInProgress = false self.WhoInProgress = false
local v,k,args = nil local v, k, args = nil
local kludge = 10 local kludge = 10
repeat repeat
k, v = self:GetNextFromScheduler() k,v = self:GetNextFromScheduler()
if not k then break end if not k then break end
if WhoFrame:IsShown() and k > self.WHOLIB_QUEUE_QUIET then if WhoFrame:IsShown() and k > self.WHOLIB_QUEUE_QUIET then
break break
@@ -443,8 +447,8 @@ function lib:AskWhoNext()
self.Result = {} self.Result = {}
self.Args = args self.Args = args
self.Total = -1 self.Total = -1
if(args.console_show == true)then if args.console_show == true then
DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_query'], args.query), 1, 1, 0) DEFAULT_CHAT_FRAME:AddMessage(format(self.L['console_query'], args.query), 1, 1, 0)
end end
@@ -453,17 +457,17 @@ function lib:AskWhoNext()
self.Quiet = false self.Quiet = false
if args.whotoui then if args.whotoui then
-- self.hooked.SetWhoToUI(args.whotoui) self.hooked.SetWhoToUI(args.whotoui)
else else
-- self.hooked.SetWhoToUI(args.gui and true or false) self.hooked.SetWhoToUI(args.gui and true or false)
end end
else else
-- self.hooked.SetWhoToUI(true) self.hooked.SetWhoToUI(true)
self.Quiet = true self.Quiet = true
end end
dbg("QUERY: "..args.query) dbg("QUERY: "..args.query)
-- self.hooked.SendWho(args.query) self.hooked.SendWho(args.query)
else else
self.Args = nil self.Args = nil
self.WhoInProgress = false self.WhoInProgress = false
@@ -478,8 +482,8 @@ function lib:AskWhoNext()
end end
function lib:AskWho(args) function lib:AskWho(args)
tinsert(self.Queue[args.queue], args) insert(self.Queue[args.queue], args)
dbg('[' .. args.queue .. '] added "' .. args.query .. '", queues=' .. getn(self.Queue[1]) .. '/'.. getn(self.Queue[2]) .. '/'.. getn(self.Queue[3])) dbg('['..args.queue..'] added "'..args.query..'", queues='..getn(self.Queue[1])..'/'.. getn(self.Queue[2])..'/'.. getn(self.Queue[3]))
self:TriggerEvent('WHOLIB_QUERY_ADDED') self:TriggerEvent('WHOLIB_QUERY_ADDED')
self:AskWhoNext() self:AskWhoNext()
@@ -491,23 +495,23 @@ function lib:ReturnWho()
return return
end end
if(self.Args.queue == self.WHOLIB_QUEUE_QUIET or self.Args.queue == self.WHOLIB_QUEUE_SCANNING)then if self.Args.queue == self.WHOLIB_QUEUE_QUIET or self.Args.queue == self.WHOLIB_QUEUE_SCANNING then
self.Quiet = nil self.Quiet = nil
end end
if queryInterval > self.MinInterval then if queryInterval > self.MinInterval then
queryInterval = queryInterval - 0.5 queryInterval = queryInterval - 0.5
dbg("--Throttling up to 1 who per " .. queryInterval .. "s") dbg("--Throttling up to 1 who per "..queryInterval.."s")
end end
self.WhoInProgress = false self.WhoInProgress = false
dbg("RESULT: "..self.Args.query) dbg("RESULT: "..self.Args.query)
dbg('[' .. self.Args.queue .. '] returned "' .. self.Args.query .. '", total=' .. self.Total ..' , queues=' .. getn(self.Queue[1]) .. '/'.. getn(self.Queue[2]) .. '/'.. getn(self.Queue[3])) dbg('['..self.Args.queue..'] returned "'..self.Args.query..'", total='..self.Total ..' , queues='..getn(self.Queue[1])..'/'.. getn(self.Queue[2])..'/'.. getn(self.Queue[3]))
local now = time() local now = time()
local complete = (self.Total == getn(self.Result)) and (self.Total < MAX_WHOS_FROM_SERVER) local complete = (self.Total == getn(self.Result)) and (self.Total < MAX_WHOS_FROM_SERVER)
for _,v in pairs(self.Result)do for _, v in pairs(self.Result)do
if v.Name then if v.Name then
if(self.Cache[v.Name] == nil)then if self.Cache[v.Name] == nil then
self.Cache[v.Name] = { inqueue = false, callback = {} } self.Cache[v.Name] = { inqueue = false, callback = {} }
end end
@@ -517,17 +521,17 @@ function lib:ReturnWho()
cachedName.data = v -- update data cachedName.data = v -- update data
cachedName.data.Online = true -- player is online cachedName.data.Online = true -- player is online
cachedName.last = now -- update timestamp cachedName.last = now -- update timestamp
if(cachedName.inqueue)then if cachedName.inqueue then
if(self.Args.info and self.CacheQueue[self.Args.query] == v.Name)then if self.Args.info and self.CacheQueue[self.Args.query] == v.Name then
-- found by the query which was created to -> remove us from query -- found by the query which was created to -> remove us from query
self.CacheQueue[self.Args.query] = nil self.CacheQueue[self.Args.query] = nil
else else
-- found by another query -- found by another query
for k2,v2 in pairs(self.CacheQueue) do for k2,v2 in pairs(self.CacheQueue) do
if(v2 == v.Name)then if v2 == v.Name then
for i=self.WHOLIB_QUEUE_QUIET, self.WHOLIB_QUEUE_SCANNING do for i = self.WHOLIB_QUEUE_QUIET, self.WHOLIB_QUEUE_SCANNING do
for k3,v3 in pairs(self.Queue[i]) do for k3,v3 in pairs(self.Queue[i]) do
if(v3.query == k2 and v3.info)then if v3.query == k2 and v3.info then
-- remove the query which was generated for this user, cause another query was faster... -- remove the query which was generated for this user, cause another query was faster...
dbg("Found '"..v.Name.."' early via query '"..self.Args.query.."'") dbg("Found '"..v.Name.."' early via query '"..self.Args.query.."'")
table.remove(self.Queue[i], k3) table.remove(self.Queue[i], k3)
@@ -538,8 +542,8 @@ function lib:ReturnWho()
end end
end end
end end
dbg('Info(' .. v.Name ..') returned: on') dbg('Info('..v.Name ..') returned: on')
for _,v2 in pairs(cachedName.callback) do for _, v2 in pairs(cachedName.callback) do
self:RaiseCallback(v2, self:ReturnUserInfo(v.Name)) self:RaiseCallback(v2, self:ReturnUserInfo(v.Name))
end end
cachedName.callback = {} cachedName.callback = {}
@@ -547,22 +551,22 @@ function lib:ReturnWho()
cachedName.inqueue = false -- query is done cachedName.inqueue = false -- query is done
end end
end end
if(self.Args.info and self.CacheQueue[self.Args.query])then if self.Args.info and self.CacheQueue[self.Args.query] then
-- the query did not deliver the result => not online! -- the query did not deliver the result => not online!
local name = self.CacheQueue[self.Args.query] local name = self.CacheQueue[self.Args.query]
local cachedName = self.Cache[name] local cachedName = self.Cache[name]
if (cachedName.inqueue)then if cachedName.inqueue then
-- nothing found (yet) -- nothing found (yet)
cachedName.valid = true -- is now valid cachedName.valid = true -- is now valid
cachedName.inqueue = false -- query is done? cachedName.inqueue = false -- query is done?
cachedName.last = now -- update timestamp cachedName.last = now -- update timestamp
if(complete)then if complete then
cachedName.data.Online = false -- player is offline cachedName.data.Online = false -- player is offline
else else
cachedName.data.Online = nil -- player is unknown (more results from who than can be displayed) cachedName.data.Online = nil -- player is unknown (more results from who than can be displayed)
end end
end end
dbg('Info(' .. name ..') returned: ' .. (cachedName.data.Online == false and 'off' or 'unkn')) dbg('Info('..name ..') returned: '..(cachedName.data.Online == false and 'off' or 'unkn'))
for _,v in pairs(cachedName.callback) do for _,v in pairs(cachedName.callback) do
self:RaiseCallback(v, self:ReturnUserInfo(name)) self:RaiseCallback(v, self:ReturnUserInfo(name))
end end
@@ -578,39 +582,39 @@ function lib:ReturnWho()
end end
function lib:GuiWho(msg) function lib:GuiWho(msg)
if(msg == self.L['gui_wait'])then if msg == self.L['gui_wait'] then
return return
end end
for _,v in pairs(self.Queue[self.WHOLIB_QUEUE_USER]) do for _,v in pairs(self.Queue[self.WHOLIB_QUEUE_USER]) do
if(v.gui == true)then if v.gui == true then
return return
end end
end end
if(self.WhoInProgress)then if self.WhoInProgress then
WhoFrameEditBox:SetText(self.L['gui_wait']) WhoFrameEditBox:SetText(self.L['gui_wait'])
end end
self.savedText = msg self.savedText = msg
self:AskWho({query = msg, queue = self.WHOLIB_QUEUE_USER, flags = 0, gui = true}) self:AskWho({query = msg, queue = self.WHOLIB_QUEUE_USER, flags = 0, gui = true})
WhoFrameEditBox:ClearFocus(); WhoFrameEditBox:ClearFocus()
end end
function lib:ConsoleWho(msg) function lib:ConsoleWho(msg)
--WhoFrameEditBox:SetText(msg) WhoFrameEditBox:SetText(msg)
local console_show = false local console_show = false
local q1 = self.Queue[self.WHOLIB_QUEUE_USER] local q1 = self.Queue[self.WHOLIB_QUEUE_USER]
local q1count = getn(q1) local q1count = getn(q1)
if(q1count > 0 and q1[q1count].query == msg)then -- last query is itdenical: drop if q1count > 0 and q1[q1count].query == msg then -- last query is itdenical: drop
return return
end end
if(q1count > 0 and q1[q1count].console_show == false)then -- display 'queued' if console and not yet shown if q1count > 0 and q1[q1count].console_show == false then -- display 'queued' if console and not yet shown
DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_queued'], q1[q1count].query), 1, 1, 0) DEFAULT_CHAT_FRAME:AddMessage(format(self.L['console_queued'], q1[q1count].query), 1, 1, 0)
q1[q1count].console_show = true q1[q1count].console_show = true
end end
if(q1count > 0 or self.WhoInProgress)then if q1count > 0 or self.WhoInProgress then
DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_queued'], msg), 1, 1, 0) DEFAULT_CHAT_FRAME:AddMessage(format(self.L['console_queued'], msg), 1, 1, 0)
console_show = true console_show = true
end end
self:AskWho({query = msg, queue = self.WHOLIB_QUEUE_USER, flags = 0, console_show = console_show}) self:AskWho({query = msg, queue = self.WHOLIB_QUEUE_USER, flags = 0, console_show = console_show})
@@ -624,10 +628,10 @@ end
function lib:RaiseCallback(args, ...) function lib:RaiseCallback(args, ...)
if type(args.callback) == 'function' then if type(args.callback) == 'function' then
args.callback(self:DupAll(unpack(args))) args.callback(self:DupAll(unpack(arg)))
elseif args.callback then -- must be a string elseif args.callback then -- must be a string
args.handler[args.callback](args.handler, self:DupAll(unpack(args))) args.handler[args.callback](args.handler, self:DupAll(unpack(arg)))
end -- if end
end end
-- Argument checking -- Argument checking
@@ -638,8 +642,8 @@ function lib:CheckArgument(func, name, argtype, arg, defarg)
elseif type(arg) == argtype then elseif type(arg) == argtype then
return arg return arg
else else
error(string.format("%s: '%s' - %s%s expected got %s", func, name, (defarg ~= nil) and 'nil or ' or '', argtype, type(arg)), 3) error(format("%s: '%s' - %s%s expected got %s", func, name, (defarg ~= nil) and 'nil or ' or '', argtype, type(arg)), 3)
end -- if end
end end
function lib:CheckPreset(func, name, preset, arg, defarg) function lib:CheckPreset(func, name, preset, arg, defarg)
@@ -651,13 +655,13 @@ function lib:CheckPreset(func, name, preset, arg, defarg)
local p = {} local p = {}
for k,v in pairs(preset) do for k,v in pairs(preset) do
if type(v) ~= 'string' then if type(v) ~= 'string' then
table.insert(p, k) insert(p, k)
else else
table.insert(p, v) insert(p, v)
end -- if end
end -- for end
error(string.format("%s: '%s' - one of %s%s expected got %s", func, name, (defarg ~= nil) and 'nil, ' or '', table.concat(p, ', '), self:simple_dump(arg)), 3) error(format("%s: '%s' - one of %s%s expected got %s", func, name, (defarg ~= nil) and 'nil, ' or '', table.concat(p, ', '), self:simple_dump(arg)), 3)
end -- if end
end end
function lib:CheckCallback(func, prefix, callback, handler, defhandler, nonil) function lib:CheckCallback(func, prefix, callback, handler, defhandler, nonil)
@@ -667,19 +671,19 @@ function lib:CheckCallback(func, prefix, callback, handler, defhandler, nonil)
elseif type(callback) == 'function' then elseif type(callback) == 'function' then
-- simple function -- simple function
if handler ~= nil then if handler ~= nil then
error(string.format("%s: '%shandler' - nil expected got %s", func, prefix, type(arg)), 3) error(format("%s: '%shandler' - nil expected got %s", func, prefix, type(arg)), 3)
end -- if end
elseif type(callback) == 'string' then elseif type(callback) == 'string' then
-- method -- method
if handler == nil then if handler == nil then
handler = defhandler handler = defhandler
end -- if end
if type(handler) ~= 'table' or type(handler[callback]) ~= 'function' or handler == self then if type(handler) ~= 'table' or type(handler[callback]) ~= 'function' or handler == self then
error(string.format("%s: '%shandler' - nil or function expected got %s", func, prefix, type(arg)), 3) error(format("%s: '%shandler' - nil or function expected got %s", func, prefix, type(arg)), 3)
end -- if end
else else
error(string.format("%s: '%scallback' - %sfunction or string expected got %s", func, prefix, nonil and 'nil or ' or '', type(arg)), 3) error(format("%s: '%scallback' - %sfunction or string expected got %s", func, prefix, nonil and 'nil or ' or '', type(arg)), 3)
end -- if end
return callback, handler return callback, handler
end end
@@ -704,26 +708,26 @@ function lib:Dup(from)
to[k] = self:Dup(v) to[k] = self:Dup(v)
else else
to[k] = v to[k] = v
end -- if end
end -- for end
return to return to
end end
function lib:DupAll(x, ...) function lib:DupAll(x, ...)
if type(x) == 'table' then if type(x) == 'table' then
return self:Dup(x), self:DupAll(unpack(args)) return self:Dup(x), self:DupAll(unpack(arg))
elseif x ~= nil then elseif x ~= nil then
return x, self:DupAll(unpack(args)) return x, self:DupAll(unpack(arg))
else else
return nil return nil
end -- if end
end end
local MULTIBYTE_FIRST_CHAR = "^([\192-\255]?%a?[\128-\191]*)" local MULTIBYTE_FIRST_CHAR = "^([\192-\255]?%a?[\128-\191]*)"
function lib:CapitalizeInitial(name) function lib:CapitalizeInitial(name)
return string.gsub(name, MULTIBYTE_FIRST_CHAR, string.upper, 1) return gsub(name, MULTIBYTE_FIRST_CHAR, string.upper, 1)
end end
--- ---
@@ -735,7 +739,7 @@ lib.PossibleEvents = {
'WHOLIB_QUERY_ADDED', 'WHOLIB_QUERY_ADDED',
} }
function lib:TriggerEvent(...) function lib:TriggerEvent(event, ...)
callbacks:Fire(event, unpack(arg)) callbacks:Fire(event, unpack(arg))
end end
@@ -745,12 +749,9 @@ end
SlashCmdList['WHO'] = function(msg) SlashCmdList['WHO'] = function(msg)
dbg("console /who: "..msg) dbg("console /who: "..msg)
-- new /who function if msg == '' then
--local self = lib
if(msg == '')then
lib:GuiWho(WhoFrame_GetDefaultWhoCommand()) lib:GuiWho(WhoFrame_GetDefaultWhoCommand())
elseif(WhoFrame:IsVisible())then elseif WhoFrame:IsVisible()then
lib:GuiWho(msg) lib:GuiWho(msg)
else else
lib:ConsoleWho(msg) lib:ConsoleWho(msg)
@@ -773,66 +774,40 @@ SLASH_WHOLIB_DEBUG1 = '/wholibdebug'
-- functions to hook -- functions to hook
local hooks = { local hooks = {
-- 'SendWho', 'SendWho',
-- 'WhoFrameEditBox_OnEnterPressed', 'WhoFrameEditBox_OnEnterPressed',
-- 'FriendsFrame_OnEvent', 'FriendsFrame_OnEvent',
-- 'SetWhoToUI', 'SetWhoToUI',
} }
-- hook all functions (which are not yet hooked) -- hook all functions (which are not yet hooked)
for _, name in pairs(hooks) do for _, name in pairs(hooks) do
if not lib['hooked'][name] then local name = name
lib['hooked'][name] = _G[name] if not lib['hooked'][name] then
_G[name] = function(...) lib['hooked'][name] = _G[name]
lib.hook[name](lib, unpack(arg)) _G[name] = function()
end -- function lib.hook[name](lib, arg1, arg2, arg3)
end -- if end
end -- for end
end
-- fake 'WhoFrame:Hide' as hooked -- fake 'WhoFrame:Hide' as hooked
table.insert(hooks, 'WhoFrame_Hide') insert(hooks, 'WhoFrame_Hide')
-- check for unused hooks -> remove function -- check for unused hooks -> remove function
for name, _ in pairs(lib['hook']) do for name, _ in pairs(lib['hook']) do
if not hooks[name] then if not hooks[name] then
lib['hook'][name] = function() end lib['hook'][name] = function() end
end -- if end
end -- for end
-- secure hook 'WhoFrame:Hide' -- secure hook 'WhoFrame:Hide'
if not lib['hooked']['WhoFrame_Hide'] then if not lib['hooked']['WhoFrame_Hide'] then
lib['hooked']['WhoFrame_Hide'] = true lib['hooked']['WhoFrame_Hide'] = true
hooksecurefunc(WhoFrame, 'Hide', function(...) hooksecurefunc(WhoFrame, 'Hide', function(...)
lib['hook']['WhoFrame_Hide'](lib, unpack(arg)) lib['hook']['WhoFrame_Hide'](lib)
end -- function end)
) end
end -- if
----- Coroutine based implementation (future)
--function lib:sendWhoResult(val)
-- coroutine.yield(val)
--end
--
--function lib:sendWaitState(val)
-- coroutine.yield(val)
--end
--
--function lib:producer()
-- return coroutine.create(
-- function()
-- lib:AskWhoNext()
-- lib:sendWaitState(true)
--
-- -- Resumed look for data
--
-- end)
--end
--- ---
--- hook replacements --- hook replacements
@@ -843,51 +818,45 @@ function lib.hook.SendWho(self, msg)
lib.AskWho(self, {query = msg, queue = lib.WHOLIB_QUEUE_USER, whotoui = lib.SetWhoToUIState, flags = 0}) lib.AskWho(self, {query = msg, queue = lib.WHOLIB_QUEUE_USER, whotoui = lib.SetWhoToUIState, flags = 0})
end end
function lib.hook.WhoFrameEditBox_OnEnterPressed(self) function lib.hook.WhoFrameEditBox_OnEnterPressed()
lib:GuiWho(WhoFrameEditBox:GetText()) lib:GuiWho(WhoFrameEditBox:GetText())
end end
--[[
function lib.hook.FriendsFrame_OnEvent(self, ...) function lib.hook.FriendsFrame_OnEvent()
if event ~= 'WHO_LIST_UPDATE' or not lib.Quiet then if event ~= 'WHO_LIST_UPDATE' or not lib.Quiet then
lib.hooked.FriendsFrame_OnEvent(...) lib.hooked.FriendsFrame_OnEvent()
end end
end end
]]
hooksecurefunc(FriendsFrame, 'RegisterEvent', function(self, event) hooksecurefunc(FriendsFrame, 'RegisterEvent', function()
if(event == "WHO_LIST_UPDATE") then if event == "WHO_LIST_UPDATE" then
self:UnregisterEvent("WHO_LIST_UPDATE"); self:UnregisterEvent("WHO_LIST_UPDATE")
end end
end); end)
function lib.hook.SetWhoToUI(_, state)
function lib.hook.SetWhoToUI(self, state)
lib.SetWhoToUIState = state lib.SetWhoToUIState = state
end end
function lib.hook.WhoFrame_Hide(self) function lib.hook.WhoFrame_Hide()
if(not lib.WhoInProgress)then if not lib.WhoInProgress then
lib:AskWhoNextIn5sec() lib:AskWhoNextIn5sec()
end end
end end
--- ---
--- WoW events --- WoW events
--- ---
local who_pattern = string.gsub(WHO_NUM_RESULTS, '%%d', '%%d%+') local who_pattern = gsub(WHO_NUM_RESULTS, '%%d', '%%d%+')
function lib:CHAT_MSG_SYSTEM()
if arg1 and find(arg1, who_pattern) then
function lib:CHAT_MSG_SYSTEM(arg1)
if arg1 and string.find(arg1, who_pattern) then
lib:ProcessWhoResults() lib:ProcessWhoResults()
end end
end end
FriendsFrame:UnregisterEvent("WHO_LIST_UPDATE") FriendsFrame:UnregisterEvent("WHO_LIST_UPDATE")
function lib:WHO_LIST_UPDATE() function lib:WHO_LIST_UPDATE()
if not lib.Quiet then if not lib.Quiet then
WhoList_Update() WhoList_Update()
@@ -902,9 +871,9 @@ function lib:ProcessWhoResults()
local num local num
self.Total, num = GetNumWhoResults() self.Total, num = GetNumWhoResults()
for i=1, num do for i = 1, num do
local charname, guildname, level, race, class, zone, nonlocalclass, sex = GetWhoInfo(i) local charname, guildname, level, race, class, zone, nonlocalclass, sex = GetWhoInfo(i)
self.Result[i] = {Name=charname, Guild=guildname, Level=level, Race=race, Class=class, Zone=zone, NoLocaleClass=nonlocalclass, Sex=sex } self.Result[i] = {Name = charname, Guild = guildname, Level = level, Race = race, Class = class, Zone = zone, NoLocaleClass = nonlocalclass, Sex = sex }
end end
self:ReturnWho() self:ReturnWho()
@@ -914,26 +883,25 @@ end
--- event activation --- event activation
--- ---
lib['frame']:UnregisterAllEvents(); lib['frame']:UnregisterAllEvents()
lib['frame']:SetScript("OnEvent", function(...) lib['frame']:SetScript("OnEvent", function(...)
lib[event](lib, unpack(arg)) lib[event](lib, unpack(arg))
end); end)
for _,name in pairs({ for _, name in pairs({
'CHAT_MSG_SYSTEM', 'CHAT_MSG_SYSTEM',
'WHO_LIST_UPDATE', 'WHO_LIST_UPDATE',
}) do }) do
lib['frame']:RegisterEvent(name); lib['frame']:RegisterEvent(name)
end -- for end
--- ---
--- re-embed --- re-embed
--- ---
for target,_ in pairs(lib['embeds']) do for target, _ in pairs(lib['embeds']) do
if type(target) == 'table' then if type(target) == 'table' then
lib:Embed(target) lib:Embed(target)
end -- if end
end -- for end