load LibWho-2.0, ClassCache & update Chat

update Chat
This commit is contained in:
Crum
2018-01-22 01:30:58 -06:00
parent dabfbfc067
commit a1b896f247
21 changed files with 1765 additions and 151 deletions
+463
View File
@@ -0,0 +1,463 @@
local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local CC = E:NewModule("ClassCache", "AceEvent-3.0");
local LW = LibStub:GetLibrary("LibWho-2.0");
--Cache global variables
--Lua functions
local split, upper = string.split, string.upper
local wipe = table.wipe
local pairs = pairs
local select = select
--WoW API / Variables
local GetBattlefieldScore = GetBattlefieldScore
local GetFriendInfo = GetFriendInfo
local GetGuildRosterInfo = GetGuildRosterInfo
local GetNumBattlefieldScores = GetNumBattlefieldScores
local GetNumFriends = GetNumFriends
local GetNumGuildMembers = GetNumGuildMembers
local GetNumPartyMembers = GetNumPartyMembers
local GetNumRaidMembers = GetNumRaidMembers
local GetTime = GetTime
local IsInGuild = IsInGuild
local UnitClass = UnitClass
local UnitExists = UnitExists
local UnitIsPlayer = UnitIsPlayer
local UnitName = UnitName
local UNKNOWN = UNKNOWN
local GAME_LOCALE = GetLocale()
local ENGLISH_CLASS_NAMES
local function GetEnglishClassName(class)
if class == UNKNOWN then
return class
elseif GAME_LOCALE == "enUS" then
return upper(class)
end
if not ENGLISH_CLASS_NAMES then
ENGLISH_CLASS_NAMES = {}
for english, localized in pairs(LOCALIZED_CLASS_NAMES_MALE) do
ENGLISH_CLASS_NAMES[localized] = english
end
for english, localized in pairs(LOCALIZED_CLASS_NAMES_FEMALE) do
ENGLISH_CLASS_NAMES[localized] = english
end
end
return ENGLISH_CLASS_NAMES[class]
end
local function WhoCallback(result)
if result then
if result.NoLocaleClass then
CC:CachePlayer(result.Name, result.NoLocaleClass)
CC:SendMessage("ClassCacheQueryResult", result.Name, result.NoLocaleClass)
end
end
end
function CC:GetClassByName(name, realm)
if not name or name == "" then return end
if realm and realm == "" then return end
if E.db.general.classCacheStoreInDB then
if realm then
if self.cache[realm] and self.cache[realm][name] then
return self.cache[realm][name]
else
return
end
else
if self.cache[E.myrealm][name] then
return self.cache[E.myrealm][name]
end
end
else
if realm then
if self.tempCache[realm] and self.tempCache[realm][name] then
return self.tempCache[realm][name]
else
return
end
else
if self.tempCache[E.myrealm][name] then
return self.tempCache[E.myrealm][name]
end
end
end
if E.db.general.classCacheRequestInfo then
local result = LW:UserInfo(name, {
queue = LW.WHOLIB_QUEUE_QUIET,
timeout = 0,
callback = function(result)
WhoCallback(result)
end
})
if result and result.NoLocaleClass then
self:CachePlayer(result.Name, result.NoLocaleClass)
return result.NoLocaleClass
end
end
end
function CC:CachePlayer(name, class, realm)
if not (name and class and class ~= UNKNOWN) then return end
if realm and realm == "" then return end
if E.db.general.classCacheStoreInDB then
if realm and not self.cache[realm] then
self.cache[realm] = {}
end
if realm then
self.cache[realm][name] = class
else
self.cache[E.myrealm][name] = class
end
else
if realm and not self.tempCache[realm] then
self.tempCache[realm] = {}
end
if realm then
self.tempCache[realm][name] = class
else
self.tempCache[E.myrealm][name] = class
end
end
end
function CC:SwitchCacheType(init)
if E.db.general.classCacheStoreInDB then
if not self.cache[E.myrealm] then
self.cache[E.myrealm] = {}
end
if not self.cache[E.myrealm][E.myname] then
self.cache[E.myrealm][E.myname] = E.myclass
end
if not init then
for realm in pairs(self.tempCache) do
if not self.cache[realm] then
self.cache[realm] = {}
end
for name, class in pairs(self.tempCache[realm]) do
self.cache[realm][name] = class
end
end
end
else
if not self.tempCache[E.myrealm] then
self.tempCache[E.myrealm] = {}
end
if not self.tempCache[E.myrealm][E.myname] then
self.tempCache[E.myrealm][E.myname] = E.myclass
end
if not init then
for realm in pairs(self.cache) do
if not self.cache[realm] then
self.tempCache[realm] = {}
end
for name, class in pairs(self.cache[realm]) do
self.tempCache[realm][name] = class
end
end
end
end
end
function CC:GetCacheTable()
if E.db.general.classCacheStoreInDB then
return self.cache
else
return self.tempCache
end
end
function CC:GetCacheSize(global)
if global and not (self.cacheDBCalculationTime + 30 < GetTime()) then
return self.cacheDBSize > 1, self.cacheDBSize
elseif not global and not (self.cacheLocalCalculationTime + 30 < GetTime()) then
return self.cacheLocalSize > 1, self.cacheLocalSize
end
local size = 0
if global then
for realm in pairs(self.cache) do
for name in pairs(self.cache[realm]) do
size = size + 1
end
end
self.cacheDBSize = size
self.cacheDBCalculationTime = GetTime()
else
for realm in pairs(self.tempCache) do
for name in pairs(self.tempCache[realm]) do
size = size + 1
end
end
self.cacheLocalSize = size
self.cacheLocalCalculationTime = GetTime()
end
return size > 1, size
end
function CC:WipeCache(global)
if global then
for realm in pairs(self.cache) do
wipe(realm)
end
wipe(self.cache)
self:SwitchCacheType(true)
self.cacheDBCalculationTime = 0
E:Print(L["Class DB cache wiped."])
else
for realm in pairs(self.tempCache) do
wipe(realm)
end
wipe(self.tempCache)
self:SwitchCacheType(true)
self.cacheLocalCalculationTime = 0
E:Print(L["Class session cache wiped."])
end
end
function CC:PLAYER_ENTERING_WORLD()
local inInstance, instanceType = IsInInstance()
self.inInstance = inInstance
if instanceType == "arena" or instanceType == "pvp" then
self.inBattleground = true
else
self.inBattleground = false
end
if self.inInstance or self.inBattleground then
self.lastNumPlayers = 0
self:UnregisterEvent("PLAYER_TARGET_CHANGED")
self:UnregisterEvent("UPDATE_MOUSEOVER_UNIT")
self:UnregisterEvent("PARTY_MEMBERS_CHANGED")
self:UnregisterEvent("RAID_ROSTER_UPDATE")
self:RegisterEvent("UPDATE_BATTLEFIELD_SCORE")
if self.inBattleground then
self:UPDATE_BATTLEFIELD_SCORE()
end
else
self.lastNumPlayers = 0
self:RegisterEvent("PLAYER_TARGET_CHANGED")
self:RegisterEvent("UPDATE_MOUSEOVER_UNIT")
self:RegisterEvent("PARTY_MEMBERS_CHANGED")
self:RegisterEvent("RAID_ROSTER_UPDATE")
self:UnregisterEvent("UPDATE_BATTLEFIELD_SCORE")
end
self:PLAYER_GUILD_UPDATE()
if not self.initUpdate then
if GetNumRaidMembers() > 0 then
self:RAID_ROSTER_UPDATE()
elseif GetNumPartyMembers() > 0 then
self:PARTY_MEMBERS_CHANGED()
end
self:GUILD_ROSTER_UPDATE(nil, true)
self.initUpdate = true
end
end
function CC:PLAYER_GUILD_UPDATE()
if IsInGuild() then
self:RegisterEvent("GUILD_ROSTER_UPDATE")
else
self:UnregisterEvent("RAID_ROSTER_UPDATE")
end
end
function CC:FRIENDLIST_UPDATE()
local name, class, _
for i = 1, GetNumFriends() do
name, _, class = GetFriendInfo(i)
if class then
self:CachePlayer(name, GetEnglishClassName(class))
end
end
end
function CC:GUILD_ROSTER_UPDATE(_, update)
if not update then return end
local name, class, _
for i = 1, GetNumGuildMembers() do
name, _, _, _, _, _, _, _, _, _, class = GetGuildRosterInfo(i)
if class then
self:CachePlayer(name, class)
end
end
end
function CC:PARTY_MEMBERS_CHANGED()
local name, realm, class, _
for i = 1, GetNumPartyMembers() do
name, realm = UnitName("party"..i)
_, class = UnitClass("party"..i)
if not class then return end
if self.inBattleground then
self:CachePlayer(name, class, realm)
else
self:CachePlayer(name, class)
end
end
end
function CC:RAID_ROSTER_UPDATE()
local name, realm, class, _
for i = 1, GetNumRaidMembers() do
name, realm = UnitName("raid"..i)
_, class = UnitClass("raid"..i)
if not class then return end
if self.inBattleground then
self:CachePlayer(name, class, realm)
else
self:CachePlayer(name, class)
end
end
end
function CC:PLAYER_TARGET_CHANGED()
if not UnitExists("target") or not UnitIsPlayer("target") then return end
local _, class = UnitClass("target")
if not class then return end
local name, realm = UnitName("target")
if self.inBattleground then
self:CachePlayer(name, class, realm)
else
self:CachePlayer(name, class)
end
end
function CC:UPDATE_MOUSEOVER_UNIT()
if not UnitExists("mouseover") or not UnitIsPlayer("mouseover") then return end
local _, class = UnitClass("mouseover")
if not class then return end
local name, realm = UnitName("mouseover")
if self.inBattleground then
self:CachePlayer(name, class, realm)
else
self:CachePlayer(name, class)
end
end
function CC:UPDATE_BATTLEFIELD_SCORE()
local numPlayers = GetNumBattlefieldScores() or 0
if self.lastNumPlayers == numPlayers then
return
elseif self.lastNumPlayers > numPlayers then
self.lastNumPlayers = numPlayers
return
end
local name, realm, class, _
for i = 1, numPlayers do
name, _, _, _, _, _, _, _, _, class = GetBattlefieldScore(i)
if name and class then
name, realm = split("-", name)
self:CachePlayer(name, class, realm)
end
end
end
function CC:WHOLIB_QUERY_RESULT(_, query, results, complete)
for _, result in pairs(results) do
if result and result.NoLocaleClass then
self:CachePlayer(result.Name, result.NoLocaleClass)
end
end
end
function CC:ToggleModule()
if E.private.general.classCache then
if not self.initialized then
self:SwitchCacheType(true)
self.initialized = true
end
self:RegisterEvent("PLAYER_ENTERING_WORLD")
self:RegisterEvent("PLAYER_GUILD_UPDATE")
self:RegisterEvent("FRIENDLIST_UPDATE")
self:RegisterEvent("PARTY_MEMBERS_CHANGED")
self:RegisterEvent("RAID_ROSTER_UPDATE")
LW.RegisterCallback(self, "WHOLIB_QUERY_RESULT", "WHOLIB_QUERY_RESULT")
else
self:UnregisterAllEvents()
LW.UnregisterAllCallbacks(self)
end
end
function CC:Initialize()
self.cache = E.global.classCache
self.tempCache = {}
self.cacheLocalCalculationTime = 0
self.cacheDBCalculationTime = 0
LW:SetWhoLibDebug(false)
if E.private.general.classCache then
self:ToggleModule()
end
end
local function InitializeCallback()
CC:Initialize()
end
E:RegisterModule(CC:GetName(), InitializeCallback)
+1
View File
@@ -14,4 +14,5 @@
<Script file="dropdown.lua"/> <Script file="dropdown.lua"/>
<Script file="Cooldowns.lua"/> <Script file="Cooldowns.lua"/>
<Script file="pluginInstaller.lua"/> <Script file="pluginInstaller.lua"/>
<Script file="ClassCache.lua"/>
</Ui> </Ui>
@@ -0,0 +1,939 @@
---
--- check for an already loaded old WhoLib
---
if WhoLibByALeX or WhoLib then
-- the WhoLib-1.0 (WhoLibByALeX) or WhoLib (by Malex) is loaded -> fail!
error("an other WhoLib is already running - disable them first!\n")
return
end -- if
---
--- check version
---
assert(LibStub, "LibWho-2.0 requires LibStub")
local major_version = 'LibWho-2.0'
local minor_version = tonumber("154") or 99999
local lib = LibStub:NewLibrary(major_version, minor_version)
if not lib then
return -- already loaded and no upgrade necessary
end
lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib)
local callbacks = lib.callbacks
local am = {}
local om = getmetatable(lib)
if om then
for k, v in pairs(om) do am[k] = v end
end
am.__tostring = function() return major_version end
setmetatable(lib, am)
local function dbgfunc(...) if lib.Debug then print(unpack(arg)) end end
local function NOP() return end
local dbg = NOP
---
--- initalize base
---
if type(lib['hooked']) ~= 'table' then
lib['hooked'] = {}
end -- if
if type(lib['hook']) ~= 'table' then
lib['hook'] = {}
end -- if
if type(lib['events']) ~= 'table' then
lib['events'] = {}
end -- if
if type(lib['embeds']) ~= 'table' then
lib['embeds'] = {}
end -- if
if type(lib['frame']) ~= 'table' then
lib['frame'] = CreateFrame('Frame', major_version);
end -- if
lib['frame']:Hide()
lib.Queue = {[1]={}, [2]={}, [3]={}}
lib.WhoInProgress = false
lib.Result = nil
lib.Args = nil
lib.Total = nil
lib.Quiet = nil
lib.Debug = false
lib.Cache = {}
lib.CacheQueue = {}
lib.SetWhoToUIState = false
lib.MinInterval = 2.5
lib.MaxInterval = 10
---
--- locale
---
if (GetLocale() == "ruRU") then
lib.L = {
['console_queued'] = 'Добавлено в очередь "/who %s"',
['console_query'] = 'Результат "/who %s"',
['gui_wait'] = '- Пожалуйста подождите -',
}
else
-- enUS is the default
lib.L = {
['console_queued'] = 'Added "/who %s" to queue',
['console_query'] = 'Result of "/who %s"',
['gui_wait'] = '- Please Wait -',
}
end -- if
---
--- external functions/constants
---
lib['external'] = {
'WHOLIB_QUEUE_USER',
'WHOLIB_QUEUE_QUIET',
'WHOLIB_QUEUE_SCANNING',
'WHOLIB_FLAG_ALWAYS_CALLBACK',
'Who',
'UserInfo',
'CachedUserInfo',
'GetWhoLibDebug',
'SetWhoLibDebug',
-- 'RegisterWhoLibEvent',
}
-- queues
lib['WHOLIB_QUEUE_USER'] = 1
lib['WHOLIB_QUEUE_QUIET'] = 2
lib['WHOLIB_QUEUE_SCANNING'] = 3
local queue_all = {
[1] = 'WHOLIB_QUEUE_USER',
[2] = 'WHOLIB_QUEUE_QUIET',
[3] = 'WHOLIB_QUEUE_SCANNING',
}
local queue_quiet = {
[2] = 'WHOLIB_QUEUE_QUIET',
[3] = 'WHOLIB_QUEUE_SCANNING',
}
-- bit masks!
lib['WHOLIB_FLAG_ALWAYS_CALLBACK'] = 1
function lib:Reset()
self.Queue = {[1]={}, [2]={}, [3]={}}
self.Cache = {}
self.CacheQueue = {}
end
function lib.Who(defhandler, query, opts)
local self, args, usage = lib, {}, 'Who(query, [opts])'
args.query = self:CheckArgument(usage, 'query', 'string', query)
opts = self:CheckArgument(usage, 'opts', 'table', opts, {})
args.queue = self:CheckPreset(usage, 'opts.queue', queue_all, opts.queue, self.WHOLIB_QUEUE_SCANNING)
args.flags = self:CheckArgument(usage, 'opts.flags', 'number', opts.flags, 0)
args.callback, args.handler = self:CheckCallback(usage, 'opts.', opts.callback, opts.handler, defhandler)
-- now args - copied and verified from opts
if args.queue == self.WHOLIB_QUEUE_USER then
if WhoFrame:IsShown() then
self:GuiWho(args.query)
else
self:ConsoleWho(args.query)
end
else
self:AskWho(args)
end
end
function lib.UserInfo(defhandler, name, opts)
local self, args, usage = lib, {}, 'UserInfo(name, [opts])'
local now = time()
name = self:CheckArgument(usage, 'name', 'string', name)
if strlen(name) == 0 then return end
if string.find(name, "%-") then --[[dbg("ignoring xrealm: "..name)]] return end
args.name = self:CapitalizeInitial(name)
opts = self:CheckArgument(usage, 'opts', 'table', opts, {})
args.queue = self:CheckPreset(usage, 'opts.queue', queue_quiet, opts.queue, self.WHOLIB_QUEUE_SCANNING)
args.flags = self:CheckArgument(usage, 'opts.flags', 'number', opts.flags, 0)
args.timeout = self:CheckArgument(usage, 'opts.timeout', 'number', opts.timeout, 5)
args.callback, args.handler = self:CheckCallback(usage, 'opts.', opts.callback, opts.handler, defhandler)
-- now args - copied and verified from opts
local cachedName = self.Cache[args.name]
if(cachedName ~= nil)then
-- user is in cache
if(cachedName.valid == true and (args.timeout < 0 or cachedName.last + args.timeout*60 > now))then
-- cache is valid and timeout is in range
--dbg('Info(' .. args.name ..') returned immedeatly')
if(bit.band(args.flags, self.WHOLIB_FLAG_ALWAYS_CALLBACK) ~= 0)then
self:RaiseCallback(args, cachedName.data)
return false
else
return self:DupAll(self:ReturnUserInfo(args.name))
end
elseif(cachedName.valid == false)then
-- query is already running (first try)
if(args.callback ~= nil)then
tinsert(cachedName.callback, args)
end
--dbg('Info(' .. args.name ..') returned cause it\'s already searching')
return nil
end
else
self.Cache[args.name] = {valid=false, inqueue=false, callback={}, data={Name = args.name}, last=now }
end
local cachedName = self.Cache[args.name]
if(cachedName.inqueue)then
-- query is running!
if(args.callback ~= nil)then
tinsert(cachedName.callback, args)
end
dbg('Info(' .. args.name ..') returned cause it\'s already searching')
return nil
end
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
local query = 'и-"' .. args.name .. '"'
cachedName.inqueue = true
if(args.callback ~= nil)then
tinsert(cachedName.callback, args)
end
self.CacheQueue[query] = args.name
dbg('Info(' .. args.name ..') added to queue')
self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } )
end
else
if args.name and strlen(args.name) > 0 then
local query = 'n-"' .. args.name .. '"'
cachedName.inqueue = true
if(args.callback ~= nil)then
tinsert(cachedName.callback, args)
end
self.CacheQueue[query] = args.name
dbg('Info(' .. args.name ..') added to queue')
self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } )
end
end
return nil
end
function lib.CachedUserInfo(_, name)
local self, usage = lib, 'CachedUserInfo(name)'
name = self:CapitalizeInitial(self:CheckArgument(usage, 'name', 'string', name))
if self.Cache[name] == nil then
return nil
else
return self:DupAll(self:ReturnUserInfo(name))
end
end
function lib.GetWhoLibDebug(_, mode)
return lib.Debug
end
function lib.SetWhoLibDebug(_, mode)
lib.Debug = mode
dbg = mode and dbgfunc or NOP
end
--function lib.RegisterWhoLibEvent(defhandler, event, callback, handler)
-- local self, usage = lib, 'RegisterWhoLibEvent(event, callback, [handler])'
--
-- self:CheckPreset(usage, 'event', self.events, event)
-- local callback, handler = self:CheckCallback(usage, '', callback, handler, defhandler, true)
-- table.insert(self.events[event], {callback=callback, handler=handler})
--end
-- non-embedded externals
function lib.Embed(_, handler)
local self, usage = lib, 'Embed(handler)'
self:CheckArgument(usage, 'handler', 'table', handler)
for _,name in pairs(self.external) do
handler[name] = self[name]
end -- do
self['embeds'][handler] = true
return handler
end
function lib.Library(_)
local self = lib
return self:Embed({})
end
---
--- internal functions
---
function lib:AllQueuesEmpty()
local queueCount = getn(self.Queue[1]) + getn(self.Queue[2]) + getn(self.Queue[3]) + getn(self.CacheQueue)
-- Be sure that we have cleared the in-progress status
if self.WhoInProgress then
queueCount = queueCount + 1
end
return queueCount == 0
end
local queryInterval = 5
function lib:GetQueryInterval() return queryInterval end
function lib:AskWhoNextIn5sec()
if self.frame:IsShown() then return end
dbg("Waiting to send next who")
self.Timeout_time = queryInterval
self['frame']:Show()
end
function lib:CancelPendingWhoNext()
lib['frame']:Hide()
end
lib['frame']:SetScript("OnUpdate", function()
lib.Timeout_time = lib.Timeout_time - arg1
if lib.Timeout_time <= 0 then
lib['frame']:Hide()
lib:AskWhoNext()
end -- if
end);
-- queue scheduler
local queue_weights = { [1] = 0.6, [2] = 0.2, [3] = 0.2 }
local queue_bounds = { [1] = 0.6, [2] = 0.2, [3] = 0.2 }
-- allow for single queries from the user to get processed faster
local lastInstantQuery = time()
local INSTANT_QUERY_MIN_INTERVAL = 60 -- only once every 1 min
function lib:UpdateWeights()
local weightsum, sum, count = 0, 0, 0
for k,v in pairs(queue_weights) do
sum = sum + v
weightsum = weightsum + v * getn(self.Queue[k])
end
if weightsum == 0 then
for k,v in pairs(queue_weights) do queue_bounds[k] = v end
return
end
local adjust = sum / weightsum
for k,v in pairs(queue_bounds) do
queue_bounds[k] = queue_weights[k] * adjust * getn(self.Queue[k])
end
end
function lib:GetNextFromScheduler()
self:UpdateWeights()
-- Since an addon could just fill up the user q for instant processing
-- we have to limit instants to 1 per INSTANT_QUERY_MIN_INTERVAL
-- and only try instant fulfilment if it will empty the user queue
if getn(self.Queue[1]) == 1 then
if time() - lastInstantQuery > INSTANT_QUERY_MIN_INTERVAL then
dbg("INSTANT")
lastInstantQuery = time()
return 1, self.Queue[1]
end
end
local n,i = math.random(),0
repeat
i=i+1
n = n - queue_bounds[i]
until i >= getn(self.Queue) or n <= 0
dbg(string.format("Q=%d, bound=%d", i, queue_bounds[i]))
if getn(self.Queue[i]) > 0 then
dbg(string.format("Q=%d, bound=%d", i, queue_bounds[i]))
return i, self.Queue[i]
else
dbg("Queues empty, waiting")
end
end
lib.queue_bounds = queue_bounds
function lib:AskWhoNext()
if lib.frame:IsShown() then
dbg("Already waiting")
return
end
self:CancelPendingWhoNext()
if self.WhoInProgress then
-- if we had a who going, it didnt complete
dbg("TIMEOUT: "..self.Args.query)
local args = self.Args
self.Args = nil
-- if args.info and self.CacheQueue[args.query] ~= nil then
dbg("Requeing "..args.query)
tinsert(self.Queue[args.queue], args)
if args.console_show ~= nil then
DEFAULT_CHAT_FRAME:AddMessage(string.format("Timeout on result of '%s' - retrying...", args.query), 1, 1, 0)
args.console_show = true
end
-- end
if queryInterval < lib.MaxInterval then
queryInterval = queryInterval + 0.5
dbg("--Throttling down to 1 who per " .. queryInterval .. "s")
end
end
self.WhoInProgress = false
local v,k,args = nil
local kludge = 10
repeat
k, v = self:GetNextFromScheduler()
if not k then break end
if WhoFrame:IsShown() and k > self.WHOLIB_QUEUE_QUIET then
break
end
if getn(v) > 0 then
args = tremove(v, 1)
break
end
kludge = kludge - 1
until kludge <= 0
if args then
self.WhoInProgress = true
self.Result = {}
self.Args = args
self.Total = -1
if(args.console_show == true)then
DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_query'], args.query), 1, 1, 0)
end
if args.queue == self.WHOLIB_QUEUE_USER then
WhoFrameEditBox:SetText(args.query)
self.Quiet = false
if args.whotoui then
self.hooked.SetWhoToUI(args.whotoui)
else
self.hooked.SetWhoToUI(args.gui and true or false)
end
else
-- self.hooked.SetWhoToUI(true)
self.Quiet = true
end
dbg("QUERY: "..args.query)
-- self.hooked.SendWho(args.query)
else
self.Args = nil
self.WhoInProgress = false
end
-- Keep processing the who queue if there is more work
if not self:AllQueuesEmpty() then
self:AskWhoNextIn5sec()
else
dbg("*** Done processing requests ***")
end
end
function lib:AskWho(args)
tinsert(self.Queue[args.queue], args)
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:AskWhoNext()
end
function lib:ReturnWho()
if not self.Args then
self.Quiet = nil
return
end
if(self.Args.queue == self.WHOLIB_QUEUE_QUIET or self.Args.queue == self.WHOLIB_QUEUE_SCANNING)then
self.Quiet = nil
end
if queryInterval > self.MinInterval then
queryInterval = queryInterval - 0.5
dbg("--Throttling up to 1 who per " .. queryInterval .. "s")
end
self.WhoInProgress = false
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]))
local now = time()
local complete = (self.Total == getn(self.Result)) and (self.Total < MAX_WHOS_FROM_SERVER)
for _,v in pairs(self.Result)do
if v.Name then
if(self.Cache[v.Name] == nil)then
self.Cache[v.Name] = { inqueue = false, callback = {} }
end
local cachedName = self.Cache[v.Name]
cachedName.valid = true -- is now valid
cachedName.data = v -- update data
cachedName.data.Online = true -- player is online
cachedName.last = now -- update timestamp
if(cachedName.inqueue)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
self.CacheQueue[self.Args.query] = nil
else
-- found by another query
for k2,v2 in pairs(self.CacheQueue) do
if(v2 == v.Name)then
for i=self.WHOLIB_QUEUE_QUIET, self.WHOLIB_QUEUE_SCANNING do
for k3,v3 in pairs(self.Queue[i]) do
if(v3.query == k2 and v3.info)then
-- remove the query which was generated for this user, cause another query was faster...
dbg("Found '"..v.Name.."' early via query '"..self.Args.query.."'")
table.remove(self.Queue[i], k3)
self.CacheQueue[k2] = nil
end
end
end
end
end
end
dbg('Info(' .. v.Name ..') returned: on')
for _,v2 in pairs(cachedName.callback) do
self:RaiseCallback(v2, self:ReturnUserInfo(v.Name))
end
cachedName.callback = {}
end
cachedName.inqueue = false -- query is done
end
end
if(self.Args.info and self.CacheQueue[self.Args.query])then
-- the query did not deliver the result => not online!
local name = self.CacheQueue[self.Args.query]
local cachedName = self.Cache[name]
if (cachedName.inqueue)then
-- nothing found (yet)
cachedName.valid = true -- is now valid
cachedName.inqueue = false -- query is done?
cachedName.last = now -- update timestamp
if(complete)then
cachedName.data.Online = false -- player is offline
else
cachedName.data.Online = nil -- player is unknown (more results from who than can be displayed)
end
end
dbg('Info(' .. name ..') returned: ' .. (cachedName.data.Online == false and 'off' or 'unkn'))
for _,v in pairs(cachedName.callback) do
self:RaiseCallback(v, self:ReturnUserInfo(name))
end
cachedName.callback = {}
self.CacheQueue[self.Args.query] = nil
end
self:RaiseCallback(self.Args, self.Args.query, self.Result, complete, self.Args.info)
self:TriggerEvent('WHOLIB_QUERY_RESULT', self.Args.query, self.Result, complete, self.Args.info)
if not self:AllQueuesEmpty() then
self:AskWhoNextIn5sec()
end
end
function lib:GuiWho(msg)
if(msg == self.L['gui_wait'])then
return
end
for _,v in pairs(self.Queue[self.WHOLIB_QUEUE_USER]) do
if(v.gui == true)then
return
end
end
if(self.WhoInProgress)then
WhoFrameEditBox:SetText(self.L['gui_wait'])
end
self.savedText = msg
self:AskWho({query = msg, queue = self.WHOLIB_QUEUE_USER, flags = 0, gui = true})
WhoFrameEditBox:ClearFocus();
end
function lib:ConsoleWho(msg)
--WhoFrameEditBox:SetText(msg)
local console_show = false
local q1 = self.Queue[self.WHOLIB_QUEUE_USER]
local q1count = getn(q1)
if(q1count > 0 and q1[q1count].query == msg)then -- last query is itdenical: drop
return
end
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)
q1[q1count].console_show = true
end
if(q1count > 0 or self.WhoInProgress)then
DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_queued'], msg), 1, 1, 0)
console_show = true
end
self:AskWho({query = msg, queue = self.WHOLIB_QUEUE_USER, flags = 0, console_show = console_show})
end
function lib:ReturnUserInfo(name)
if(name ~= nil and self ~= nil and self.Cache ~= nil and self.Cache[name] ~= nil) then
return self.Cache[name].data, (time() - self.Cache[name].last) / 60
end
end
function lib:RaiseCallback(args, ...)
if type(args.callback) == 'function' then
args.callback(self:DupAll(unpack(args)))
elseif args.callback then -- must be a string
args.handler[args.callback](args.handler, self:DupAll(unpack(args)))
end -- if
end
-- Argument checking
function lib:CheckArgument(func, name, argtype, arg, defarg)
if arg == nil and defarg ~= nil then
return defarg
elseif type(arg) == argtype then
return arg
else
error(string.format("%s: '%s' - %s%s expected got %s", func, name, (defarg ~= nil) and 'nil or ' or '', argtype, type(arg)), 3)
end -- if
end
function lib:CheckPreset(func, name, preset, arg, defarg)
if arg == nil and defarg ~= nil then
return defarg
elseif arg ~= nil and preset[arg] ~= nil then
return arg
else
local p = {}
for k,v in pairs(preset) do
if type(v) ~= 'string' then
table.insert(p, k)
else
table.insert(p, v)
end -- if
end -- for
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)
end -- if
end
function lib:CheckCallback(func, prefix, callback, handler, defhandler, nonil)
if not nonil and callback == nil then
-- no callback: ignore handler
return nil, nil
elseif type(callback) == 'function' then
-- simple function
if handler ~= nil then
error(string.format("%s: '%shandler' - nil expected got %s", func, prefix, type(arg)), 3)
end -- if
elseif type(callback) == 'string' then
-- method
if handler == nil then
handler = defhandler
end -- if
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)
end -- if
else
error(string.format("%s: '%scallback' - %sfunction or string expected got %s", func, prefix, nonil and 'nil or ' or '', type(arg)), 3)
end -- if
return callback, handler
end
-- helpers
function lib:simple_dump(x)
if type(x) == 'string' then
return 'string \''..x..'\''
elseif type(x) == 'number' then
return 'number '..x
else
return type(x)
end
end
function lib:Dup(from)
local to = {}
for k,v in pairs(from) do
if type(v) == 'table' then
to[k] = self:Dup(v)
else
to[k] = v
end -- if
end -- for
return to
end
function lib:DupAll(x, ...)
if type(x) == 'table' then
return self:Dup(x), self:DupAll(unpack(args))
elseif x ~= nil then
return x, self:DupAll(unpack(args))
else
return nil
end -- if
end
local MULTIBYTE_FIRST_CHAR = "^([\192-\255]?%a?[\128-\191]*)"
function lib:CapitalizeInitial(name)
return string.gsub(name, MULTIBYTE_FIRST_CHAR, string.upper, 1)
end
---
--- user events (Using CallbackHandler)
---
lib.PossibleEvents = {
'WHOLIB_QUERY_RESULT',
'WHOLIB_QUERY_ADDED',
}
function lib:TriggerEvent(...)
callbacks:Fire(event, unpack(arg))
end
---
--- slash commands
---
SlashCmdList['WHO'] = function(msg)
dbg("console /who: "..msg)
-- new /who function
--local self = lib
if(msg == '')then
lib:GuiWho(WhoFrame_GetDefaultWhoCommand())
elseif(WhoFrame:IsVisible())then
lib:GuiWho(msg)
else
lib:ConsoleWho(msg)
end
end
SlashCmdList['WHOLIB_DEBUG'] = function()
-- /wholibdebug: toggle debug on/off
local self = lib
self:SetWhoLibDebug(not self.Debug)
end
SLASH_WHOLIB_DEBUG1 = '/wholibdebug'
---
--- hook activation
---
-- functions to hook
local hooks = {
-- 'SendWho',
-- 'WhoFrameEditBox_OnEnterPressed',
-- 'FriendsFrame_OnEvent',
-- 'SetWhoToUI',
}
-- hook all functions (which are not yet hooked)
for _, name in pairs(hooks) do
if not lib['hooked'][name] then
lib['hooked'][name] = _G[name]
_G[name] = function(...)
lib.hook[name](lib, unpack(arg))
end -- function
end -- if
end -- for
-- fake 'WhoFrame:Hide' as hooked
table.insert(hooks, 'WhoFrame_Hide')
-- check for unused hooks -> remove function
for name, _ in pairs(lib['hook']) do
if not hooks[name] then
lib['hook'][name] = function() end
end -- if
end -- for
-- secure hook 'WhoFrame:Hide'
if not lib['hooked']['WhoFrame_Hide'] then
lib['hooked']['WhoFrame_Hide'] = true
hooksecurefunc(WhoFrame, 'Hide', function(...)
lib['hook']['WhoFrame_Hide'](lib, unpack(arg))
end -- function
)
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
---
function lib.hook.SendWho(self, msg)
dbg("SendWho: "..msg)
lib.AskWho(self, {query = msg, queue = lib.WHOLIB_QUEUE_USER, whotoui = lib.SetWhoToUIState, flags = 0})
end
function lib.hook.WhoFrameEditBox_OnEnterPressed(self)
lib:GuiWho(WhoFrameEditBox:GetText())
end
--[[
function lib.hook.FriendsFrame_OnEvent(self, ...)
if event ~= 'WHO_LIST_UPDATE' or not lib.Quiet then
lib.hooked.FriendsFrame_OnEvent(...)
end
end
]]
hooksecurefunc(FriendsFrame, 'RegisterEvent', function(self, event)
if(event == "WHO_LIST_UPDATE") then
self:UnregisterEvent("WHO_LIST_UPDATE");
end
end);
function lib.hook.SetWhoToUI(self, state)
lib.SetWhoToUIState = state
end
function lib.hook.WhoFrame_Hide(self)
if(not lib.WhoInProgress)then
lib:AskWhoNextIn5sec()
end
end
---
--- WoW events
---
local who_pattern = string.gsub(WHO_NUM_RESULTS, '%%d', '%%d%+')
function lib:CHAT_MSG_SYSTEM(arg1)
if arg1 and string.find(arg1, who_pattern) then
lib:ProcessWhoResults()
end
end
FriendsFrame:UnregisterEvent("WHO_LIST_UPDATE")
function lib:WHO_LIST_UPDATE()
if not lib.Quiet then
WhoList_Update()
FriendsFrame_Update()
end
lib:ProcessWhoResults()
end
function lib:ProcessWhoResults()
self.Result = self.Result and table.wipe(self.Result) or {}
local num
self.Total, num = GetNumWhoResults()
for i=1, num do
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 }
end
self:ReturnWho()
end
---
--- event activation
---
lib['frame']:UnregisterAllEvents();
lib['frame']:SetScript("OnEvent", function(...)
lib[event](lib, unpack(arg))
end);
for _,name in pairs({
'CHAT_MSG_SYSTEM',
'WHO_LIST_UPDATE',
}) do
lib['frame']:RegisterEvent(name);
end -- for
---
--- re-embed
---
for target,_ in pairs(lib['embeds']) do
if type(target) == 'table' then
lib:Embed(target)
end -- if
end -- for
@@ -0,0 +1,4 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<Script file="LibWho-2.0.lua"/>
</Ui>
@@ -20,6 +20,7 @@
<Include file="LibCompress\LibCompress.xml"/> <Include file="LibCompress\LibCompress.xml"/>
<Include file="LibBase64-1.0\LibBase64-1.0.xml"/> <Include file="LibBase64-1.0\LibBase64-1.0.xml"/>
<Include file="LibAnim\LibAnim.xml"/> <Include file="LibAnim\LibAnim.xml"/>
<Include file="LibWho-2.0\LibWho-2.0.xml"/>
<Include file="LibUIDropDownMenu\LibUIDropDownMenu.xml"/> <Include file="LibUIDropDownMenu\LibUIDropDownMenu.xml"/>
<Include file="LibItemSearch-1.2\LibItemSearch-1.2.xml"/> <Include file="LibItemSearch-1.2\LibItemSearch-1.2.xml"/>
</Ui> </Ui>
+167 -128
View File
@@ -1,6 +1,6 @@
local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local CH = E:NewModule("Chat", "AceTimer-3.0", "AceHook-3.0", "AceEvent-3.0"); local CH = E:NewModule("Chat", "AceTimer-3.0", "AceHook-3.0", "AceEvent-3.0");
--local CC = E:GetModule("ClassCache") local CC = E:GetModule("ClassCache");
local LSM = LibStub("LibSharedMedia-3.0"); local LSM = LibStub("LibSharedMedia-3.0");
--Cache global variables --Cache global variables
@@ -212,6 +212,45 @@ local function ChatFrame_OnMouseScroll(frame, delta)
end end
end end
local function ChatFrame_AddMessageEventFilter(event, filter)
assert(event and filter)
if chatFilters[event] then
-- Only allow a filter to be added once
for index, filterFunc in next, chatFilters[event] do
if filterFunc == filter then
return
end
end
else
chatFilters[event] = {}
end
tinsert(chatFilters[event], filter)
end
local function ChatFrame_RemoveMessageEventFilter(event, filter)
assert(event and filter)
if chatFilters[event] then
for index, filterFunc in next, chatFilters[event] do
if filterFunc == filter then
tremove(chatFilters[event], index)
end
end
if getn(chatFilters[event]) == 0 then
chatFilters[event] = nil
end
end
end
local function ChatFrame_GetMessageEventFilters(event)
assert(event)
return chatFilters[event]
end
function CH:GetGroupDistribution() function CH:GetGroupDistribution()
local inInstance, kind = IsInInstance() local inInstance, kind = IsInInstance()
if inInstance and kind == "pvp" then if inInstance and kind == "pvp" then
@@ -228,7 +267,7 @@ end
function CH:InsertEmotions(msg) function CH:InsertEmotions(msg)
for k,v in pairs(smileyKeys) do for k,v in pairs(smileyKeys) do
msg = gsub(msg,k,"|T"..smileyPack[v]..":16|t") -- msg = gsub(msg,k,"|T"..smileyPack[v]..":16|t")
end end
return msg return msg
end end
@@ -362,7 +401,7 @@ end
local function removeIconFromLine(text) local function removeIconFromLine(text)
text = gsub(text, "|TInterface\\TargetingFrame\\UI%-RaidTargetingIcon_(%d+):0|t", function(x) text = gsub(text, "|TInterface\\TargetingFrame\\UI%-RaidTargetingIcon_(%d+):0|t", function(x)
x = _G["RAID_TARGET_"..x];return "{"..strlower(x).."}" x = _G["RAID_TARGET_"..x]; return "{"..strlower(x).."}"
end) end)
text = gsub(text, "|H.-|h(.-)|h", "%1") text = gsub(text, "|H.-|h(.-)|h", "%1")
@@ -712,8 +751,8 @@ function CH:OnHyperlinkLeave()
end end
end end
function CH:OnMessageScrollChanged(frame) function CH:OnMessageScrollChanged()
if hyperLinkEntered == frame then if hyperLinkEntered == this then
HideUIPanel(GameTooltip) HideUIPanel(GameTooltip)
hyperLinkEntered = false hyperLinkEntered = false
end end
@@ -750,7 +789,7 @@ function CH.ShortChannel()
end end
function CH:ConcatenateTimeStamp(msg) function CH:ConcatenateTimeStamp(msg)
if (CH.db.timeStampFormat and CH.db.timeStampFormat ~= "NONE" ) then if CH.db.timeStampFormat and CH.db.timeStampFormat ~= "NONE" then
local timeStamp = BetterDate(CH.db.timeStampFormat, CH.timeOverride or time()) local timeStamp = BetterDate(CH.db.timeStampFormat, CH.timeOverride or time())
timeStamp = gsub(timeStamp, " ", "") timeStamp = gsub(timeStamp, " ", "")
timeStamp = gsub(timeStamp, "AM", " AM") timeStamp = gsub(timeStamp, "AM", " AM")
@@ -773,7 +812,7 @@ function GetColoredName(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, a
if arg2 and arg2 ~= "" then if arg2 and arg2 ~= "" then
local name, realm = strsplit("-", arg2) local name, realm = strsplit("-", arg2)
--local englishClass = CC:GetClassByName(name, realm) local englishClass = CC:GetClassByName(name, realm)
if englishClass then if englishClass then
local classColorTable = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[englishClass] or RAID_CLASS_COLORS[englishClass] local classColorTable = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[englishClass] or RAID_CLASS_COLORS[englishClass]
@@ -802,112 +841,112 @@ end
function CH:ChatFrame_MessageEventHandler(event, ...) function CH:ChatFrame_MessageEventHandler(event, ...)
if event == "UPDATE_CHAT_WINDOWS" then if event == "UPDATE_CHAT_WINDOWS" then
local name, fontSize, r, g, b, a, shown, locked = GetChatWindowInfo(self:GetID()); local name, fontSize, r, g, b, a, shown, locked = GetChatWindowInfo(self:GetID())
if ( fontSize > 0 ) then if fontSize > 0 then
local fontFile, unused, fontFlags = self:GetFont(); local fontFile, unused, fontFlags = self:GetFont()
self:SetFont(fontFile, fontSize, fontFlags); self:SetFont(fontFile, fontSize, fontFlags)
end end
if ( shown ) then if shown then
self:Show(); self:Show()
end end
-- Do more stuff!!! -- Do more stuff!!!
ChatFrame_RegisterForMessages(GetChatWindowMessages(self:GetID())); ChatFrame_RegisterForMessages(GetChatWindowMessages(self:GetID()))
ChatFrame_RegisterForChannels(GetChatWindowChannels(self:GetID())); ChatFrame_RegisterForChannels(GetChatWindowChannels(self:GetID()))
return; return
end end
if ( event == "PLAYER_ENTERING_WORLD" ) then if event == "PLAYER_ENTERING_WORLD" then
self.defaultLanguage = GetDefaultLanguage(); self.defaultLanguage = GetDefaultLanguage()
return; return
end end
if ( event == "TIME_PLAYED_MSG" ) then if event == "TIME_PLAYED_MSG" then
ChatFrame_DisplayTimePlayed(arg1, arg2); ChatFrame_DisplayTimePlayed(arg1, arg2)
return; return
end end
if ( event == "PLAYER_LEVEL_UP" ) then if event == "PLAYER_LEVEL_UP" then
-- Level up -- Level up
local info = ChatTypeInfo["SYSTEM"]; local info = ChatTypeInfo["SYSTEM"]
local string = format(TEXT(LEVEL_UP), arg1); local string = format(TEXT(LEVEL_UP), arg1)
self:AddMessage(string, info.r, info.g, info.b, info.id); self:AddMessage(string, info.r, info.g, info.b, info.id)
if ( arg3 > 0 ) then if arg3 > 0 then
string = format(TEXT(LEVEL_UP_HEALTH_MANA), arg2, arg3); string = format(TEXT(LEVEL_UP_HEALTH_MANA), arg2, arg3)
else else
string = format(TEXT(LEVEL_UP_HEALTH), arg2); string = format(TEXT(LEVEL_UP_HEALTH), arg2)
end end
self:AddMessage(string, info.r, info.g, info.b, info.id); self:AddMessage(string, info.r, info.g, info.b, info.id)
if ( arg4 > 0 ) then if arg4 > 0 then
string = format(GetText("LEVEL_UP_CHAR_POINTS", nil, arg4), arg4); string = format(GetText("LEVEL_UP_CHAR_POINTS", nil, arg4), arg4)
self:AddMessage(string, info.r, info.g, info.b, info.id); self:AddMessage(string, info.r, info.g, info.b, info.id)
end end
if ( arg5 > 0 ) then if arg5 > 0 then
string = format(TEXT(LEVEL_UP_STAT), TEXT(SPELL_STAT0_NAME), arg5); string = format(TEXT(LEVEL_UP_STAT), TEXT(SPELL_STAT0_NAME), arg5)
self:AddMessage(string, info.r, info.g, info.b, info.id); self:AddMessage(string, info.r, info.g, info.b, info.id)
end end
if ( arg6 > 0 ) then if arg6 > 0 then
string = format(TEXT(LEVEL_UP_STAT), TEXT(SPELL_STAT1_NAME), arg6); string = format(TEXT(LEVEL_UP_STAT), TEXT(SPELL_STAT1_NAME), arg6)
self:AddMessage(string, info.r, info.g, info.b, info.id); self:AddMessage(string, info.r, info.g, info.b, info.id)
end end
if ( arg7 > 0 ) then if arg7 > 0 then
string = format(TEXT(LEVEL_UP_STAT), TEXT(SPELL_STAT2_NAME), arg7); string = format(TEXT(LEVEL_UP_STAT), TEXT(SPELL_STAT2_NAME), arg7)
self:AddMessage(string, info.r, info.g, info.b, info.id); self:AddMessage(string, info.r, info.g, info.b, info.id)
end end
if ( arg8 > 0 ) then if arg8 > 0 then
string = format(TEXT(LEVEL_UP_STAT), TEXT(SPELL_STAT3_NAME), arg8); string = format(TEXT(LEVEL_UP_STAT), TEXT(SPELL_STAT3_NAME), arg8)
self:AddMessage(string, info.r, info.g, info.b, info.id); self:AddMessage(string, info.r, info.g, info.b, info.id)
end end
if ( arg9 > 0 ) then if arg9 > 0 then
string = format(TEXT(LEVEL_UP_STAT), TEXT(SPELL_STAT4_NAME), arg9); string = format(TEXT(LEVEL_UP_STAT), TEXT(SPELL_STAT4_NAME), arg9)
self:AddMessage(string, info.r, info.g, info.b, info.id); self:AddMessage(string, info.r, info.g, info.b, info.id)
end end
return; return
end end
if ( event == "CHARACTER_POINTS_CHANGED" ) then if event == "CHARACTER_POINTS_CHANGED" then
local info = ChatTypeInfo["SYSTEM"]; local info = ChatTypeInfo["SYSTEM"]
if ( arg2 > 0 ) then if arg2 > 0 then
local cp1, cp2 = UnitCharacterPoints("player"); local cp1, cp2 = UnitCharacterPoints("player")
if ( cp2 ) then if cp2 then
local string = format(GetText("LEVEL_UP_SKILL_POINTS", nil, cp2), cp2); local string = format(GetText("LEVEL_UP_SKILL_POINTS", nil, cp2), cp2)
self:AddMessage(string, info.r, info.g, info.b, info.id); self:AddMessage(string, info.r, info.g, info.b, info.id)
end end
end end
return; return
end end
if ( event == "GUILD_MOTD" ) then if event == "GUILD_MOTD" then
if ( arg1 and (strlen(arg1) > 0) ) then if arg1 and (strlen(arg1) > 0) then
local info = ChatTypeInfo["GUILD"]; local info = ChatTypeInfo["GUILD"]
local string = format(TEXT(GUILD_MOTD_TEMPLATE), arg1); local string = format(TEXT(GUILD_MOTD_TEMPLATE), arg1)
self:AddMessage(string, info.r, info.g, info.b, info.id); self:AddMessage(string, info.r, info.g, info.b, info.id)
end end
return; return
end end
if ( event == "EXECUTE_CHAT_LINE" ) then if event == "EXECUTE_CHAT_LINE" then
self.editBox:SetText(arg1); self.editBox:SetText(arg1)
ChatEdit_SendText(self.editBox); ChatEdit_SendText(self.editBox)
ChatEdit_OnEscapePressed(self.editBox); ChatEdit_OnEscapePressed(self.editBox)
return; return
end end
if ( event == "UPDATE_CHAT_COLOR" ) then if event == "UPDATE_CHAT_COLOR" then
local info = ChatTypeInfo[strupper(arg1)]; local info = ChatTypeInfo[strupper(arg1)]
if ( info ) then if info then
info.r = arg2; info.r = arg2
info.g = arg3; info.g = arg3
info.b = arg4; info.b = arg4
self:UpdateColorByID(info.id, info.r, info.g, info.b); self:UpdateColorByID(info.id, info.r, info.g, info.b)
if ( strupper(arg1) == "WHISPER" ) then if strupper(arg1) == "WHISPER" then
info = ChatTypeInfo["REPLY"]; info = ChatTypeInfo["REPLY"]
if ( info ) then if info then
info.r = arg2; info.r = arg2
info.g = arg3; info.g = arg3
info.b = arg4; info.b = arg4
self:UpdateColorByID(info.id, info.r, info.g, info.b); self:UpdateColorByID(info.id, info.r, info.g, info.b)
end end
end end
end end
return; return
end end
if strsub(event, 1, 8) == "CHAT_MSG" then if strsub(event, 1, 8) == "CHAT_MSG" then
local type = strsub(event, 10) local type = strsub(event, 10)
@@ -954,7 +993,7 @@ function CH:ChatFrame_MessageEventHandler(event, ...)
end end
end end
end end
if (found == 0) or not info then if found == 0 or not info then
return true return true
end end
end end
@@ -1031,15 +1070,15 @@ function CH:ChatFrame_MessageEventHandler(event, ...)
arg1 = gsub(arg1, "%%", "%%%%") arg1 = gsub(arg1, "%%", "%%%%")
end end
local showLink = 1; local showLink = 1
if ( strsub(type, 1, 7) == "MONSTER" or type == "RAID_BOSS_EMOTE" ) then if strsub(type, 1, 7) == "MONSTER" or type == "RAID_BOSS_EMOTE" then
showLink = nil; showLink = nil
else else
arg1 = gsub(arg1, "%%", "%%%%"); arg1 = gsub(arg1, "%%", "%%%%")
end end
if (strlen(arg3) > 0) and (arg3 ~= "Universal") and (arg3 ~= GetDefaultLanguage()) then if (strlen(arg3) > 0) and (arg3 ~= "Universal") and (arg3 ~= GetDefaultLanguage()) then
local languageHeader = "["..arg3.."] " local languageHeader = "["..arg3.."] "
if ( showLink and (strlen(arg2) > 0) ) then if showLink and (strlen(arg2) > 0) then
body = format(_G["CHAT_"..type.."_GET"]..languageHeader..arg1, pflag.."|Hplayer:"..arg2.."|h".."["..arg2.."]".."|h") body = format(_G["CHAT_"..type.."_GET"]..languageHeader..arg1, pflag.."|Hplayer:"..arg2.."|h".."["..arg2.."]".."|h")
else else
body = format(_G["CHAT_"..type.."_GET"]..languageHeader..arg1, pflag..arg2) body = format(_G["CHAT_"..type.."_GET"]..languageHeader..arg1, pflag..arg2)
@@ -1122,7 +1161,7 @@ local function OnTextChanged(self)
if strsub(text, 1, 4) == "/tt " then if strsub(text, 1, 4) == "/tt " then
local unitname, realm = UnitName("target") local unitname, realm = UnitName("target")
if unitname and realm then if unitname and realm then
unitname = unitname .. "-" .. realm:gsub(" ", "") unitname = unitname .. "-" .. gsub(realm, " ", "")
end end
ChatFrame_SendTell((unitname or L["Invalid Target"]), ChatFrame1) ChatFrame_SendTell((unitname or L["Invalid Target"]), ChatFrame1)
end end
@@ -1135,7 +1174,7 @@ local function OnTextChanged(self)
local new, found = gsub(text, "|Kf(%S+)|k(%S+)%s(%S+)|k", "%2 %3") local new, found = gsub(text, "|Kf(%S+)|k(%S+)%s(%S+)|k", "%2 %3")
if found > 0 then if found > 0 then
new = new:gsub("|", "") new = gsub(new, "|", "")
self:SetText(new) self:SetText(new)
end end
end end
@@ -1287,8 +1326,8 @@ end
local protectLinks = {} local protectLinks = {}
function CH:CheckKeyword(message) function CH:CheckKeyword(message)
for itemLink in message:gmatch("|%x+|Hitem:.-|h.-|h|r") do for itemLink in gmatch(message, "|%x+|Hitem:.-|h.-|h|r") do
protectLinks[itemLink] = itemLink:gsub("%s","|s") protectLinks[itemLink] = gsub(itemLink, "%s","|s")
for keyword, _ in pairs(CH.Keywords) do for keyword, _ in pairs(CH.Keywords) do
if itemLink == keyword then if itemLink == keyword then
if self.db.keywordSound ~= "None" and not self.SoundPlayed then if self.db.keywordSound ~= "None" and not self.SoundPlayed then
@@ -1301,17 +1340,17 @@ function CH:CheckKeyword(message)
end end
for itemLink, tempLink in pairs(protectLinks) do for itemLink, tempLink in pairs(protectLinks) do
message = message:gsub(itemLink:gsub("([%(%)%.%%%+%-%*%?%[%^%$])","%%%1"), tempLink) message = gsub(message, gsub(itemLink, "([%(%)%.%%%+%-%*%?%[%^%$])","%%%1"), tempLink)
end end
local classColorTable, tempWord, rebuiltString, lowerCaseWord, wordMatch, classMatch local classColorTable, tempWord, rebuiltString, lowerCaseWord, wordMatch, classMatch
local isFirstWord = true local isFirstWord = true
for word in message:gmatch("%s-[^%s]+%s*") do for word in gmatch(message, "%s-[^%s]+%s*") do
tempWord = word:gsub("[%s%p]", "") tempWord = gsub(word, "[%s%p]", "")
lowerCaseWord = tempWord:lower() lowerCaseWord = strlower(tempWord)
for keyword, _ in pairs(CH.Keywords) do for keyword, _ in pairs(CH.Keywords) do
if lowerCaseWord == keyword:lower() then if lowerCaseWord == strlower(keyword) then
word = word:gsub(tempWord, format("%s%s|r", E.media.hexvaluecolor, tempWord)) word = gsub(word, tempWord, format("%s%s|r", E.media.hexvaluecolor, tempWord))
if self.db.keywordSound ~= "None" and not self.SoundPlayed then if self.db.keywordSound ~= "None" and not self.SoundPlayed then
PlaySoundFile(LSM:Fetch("sound", self.db.keywordSound), "Master") PlaySoundFile(LSM:Fetch("sound", self.db.keywordSound), "Master")
self.SoundPlayed = true self.SoundPlayed = true
@@ -1321,14 +1360,14 @@ function CH:CheckKeyword(message)
end end
if self.db.classColorMentionsChat and E.private.general.classCache then if self.db.classColorMentionsChat and E.private.general.classCache then
tempWord = word:gsub("^[%s%p]-([^%s%p]+)([%-]?[^%s%p]-)[%s%p]*$","%1%2") tempWord = gsub(word, "^[%s%p]-([^%s%p]+)([%-]?[^%s%p]-)[%s%p]*$","%1%2")
--classMatch = CC:GetCacheTable()[E.myrealm][tempWord] classMatch = CC:GetCacheTable()[E.myrealm][tempWord]
wordMatch = classMatch and lowerCaseWord wordMatch = classMatch and lowerCaseWord
if wordMatch and not E.global.chat.classColorMentionExcludedNames[wordMatch] then if wordMatch and not E.global.chat.classColorMentionExcludedNames[wordMatch] then
classColorTable = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[classMatch] or RAID_CLASS_COLORS[classMatch] classColorTable = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[classMatch] or RAID_CLASS_COLORS[classMatch]
word = word:gsub(tempWord:gsub("%-","%%-"), format("\124cff%.2x%.2x%.2x%s\124r", classColorTable.r*255, classColorTable.g*255, classColorTable.b*255, tempWord)) word = gsub(word, gsub(tempWord, "%-","%%-"), format("\124cff%.2x%.2x%.2x%s\124r", classColorTable.r*255, classColorTable.g*255, classColorTable.b*255, tempWord))
end end
end end
@@ -1341,7 +1380,7 @@ function CH:CheckKeyword(message)
end end
for itemLink, tempLink in pairs(protectLinks) do for itemLink, tempLink in pairs(protectLinks) do
rebuiltString = rebuiltString:gsub(tempLink:gsub("([%(%)%.%%%+%-%*%?%[%^%$])","%%%1"), itemLink) rebuiltString = gsub(rebuiltString, gsub(tempLink, "([%(%)%.%%%+%-%*%?%[%^%$])","%%%1"), itemLink)
protectLinks[itemLink] = nil protectLinks[itemLink] = nil
end end
@@ -1652,34 +1691,34 @@ function CH:Initialize()
end end
--First get all pre-existing filters and copy them to our version of chatFilters using ChatFrame_GetMessageEventFilters --First get all pre-existing filters and copy them to our version of chatFilters using ChatFrame_GetMessageEventFilters
--for name, _ in pairs(ChatTypeGroup) do for name, _ in pairs(ChatTypeGroup) do
-- for i = 1, getn(ChatTypeGroup[name]) do for i = 1, getn(ChatTypeGroup[name]) do
-- local filterFuncTable = ChatFrame_GetMessageEventFilters(ChatTypeGroup[name][i]) local filterFuncTable = ChatFrame_GetMessageEventFilters(ChatTypeGroup[name][i])
-- if filterFuncTable then if filterFuncTable then
-- chatFilters[ChatTypeGroup[name][i]] = {} chatFilters[ChatTypeGroup[name][i]] = {}
--
-- for j = 1, getn(filterFuncTable) do for j = 1, getn(filterFuncTable) do
-- local filterFunc = filterFuncTable[j] local filterFunc = filterFuncTable[j]
-- tinsert(chatFilters[ChatTypeGroup[name][i]], filterFunc) tinsert(chatFilters[ChatTypeGroup[name][i]], filterFunc)
-- end end
-- end end
-- end end
--end end
--CHAT_MSG_CHANNEL isn't located inside ChatTypeGroup --CHAT_MSG_CHANNEL isn't located inside ChatTypeGroup
--local filterFuncTable = ChatFrame_GetMessageEventFilters("CHAT_MSG_CHANNEL") local filterFuncTable = ChatFrame_GetMessageEventFilters("CHAT_MSG_CHANNEL")
--if filterFuncTable then if filterFuncTable then
-- chatFilters["CHAT_MSG_CHANNEL"] = {} chatFilters["CHAT_MSG_CHANNEL"] = {}
--
-- for j = 1, getn(filterFuncTable) do for j = 1, getn(filterFuncTable) do
-- local filterFunc = filterFuncTable[j] local filterFunc = filterFuncTable[j]
-- tinsert(chatFilters["CHAT_MSG_CHANNEL"], filterFunc) tinsert(chatFilters["CHAT_MSG_CHANNEL"], filterFunc)
-- end end
--end end
--Now hook onto Blizzards functions for other addons --Now hook onto Blizzards functions for other addons
--self:SecureHook("ChatFrame_AddMessageEventFilter") hooksecurefunc(self, "ChatFrame_AddMessageEventFilter", ChatFrame_AddMessageEventFilter)
--self:SecureHook("ChatFrame_RemoveMessageEventFilter") hooksecurefunc(self, "ChatFrame_RemoveMessageEventFilter", ChatFrame_RemoveMessageEventFilter)
self:SecureHook("FCF_SetWindowAlpha") self:SecureHook("FCF_SetWindowAlpha")
@@ -1700,7 +1739,7 @@ function CH:Initialize()
end end
for _, event in pairs(FindURL_Events) do for _, event in pairs(FindURL_Events) do
--ChatFrame_AddMessageEventFilter(event, CH[event] or CH.FindURL) ChatFrame_AddMessageEventFilter(event, CH[event] or CH.FindURL)
local nType = strsub(event, 10) local nType = strsub(event, 10)
if nType ~= "AFK" and nType ~= "DND" then if nType ~= "AFK" and nType ~= "DND" then
self:RegisterEvent(event, "SaveChatHistory") self:RegisterEvent(event, "SaveChatHistory")
@@ -1,12 +1,12 @@
local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local M = E:GetModule("Misc"); local M = E:GetModule("Misc");
-- local CH = E:GetModule("Chat"); local CH = E:GetModule("Chat");
-- local CC = E:GetModule("ClassCache"); local CC = E:GetModule("ClassCache");
--Cache global variables --Cache global variables
--Lua functions --Lua functions
local select, unpack, type = select, unpack, type local select, unpack, type = select, unpack, type
local format, gsub = string.format, string.gsub local format, gsub, match, gmatch = string.format, string.gsub, string.match, string.gmatch
local strlower = strlower local strlower = strlower
--WoW API / Variables --WoW API / Variables
local CreateFrame = CreateFrame local CreateFrame = CreateFrame
@@ -29,17 +29,17 @@ function M:UpdateBubbleBorder()
if E.private.chat.enable and E.private.general.classCache and E.private.general.classColorMentionsSpeech then if E.private.chat.enable and E.private.general.classCache and E.private.general.classColorMentionsSpeech then
local classColorTable, isFirstWord, rebuiltString, lowerCaseWord, tempWord, wordMatch, classMatch local classColorTable, isFirstWord, rebuiltString, lowerCaseWord, tempWord, wordMatch, classMatch
local text = this.text:GetText() local text = this.text:GetText()
if text and text:match("%s-[^%s]+%s*") then if text and match(text, "%s-[^%s]+%s*") then
for word in text:gmatch("%s-[^%s]+%s*") do for word in gmatch(text, "%s-[^%s]+%s*") do
tempWord = word:gsub("^[%s%p]-([^%s%p]+)([%-]?[^%s%p]-)[%s%p]*$","%1%2") tempWord = gsub(word, "^[%s%p]-([^%s%p]+)([%-]?[^%s%p]-)[%s%p]*$","%1%2")
lowerCaseWord = tempWord:lower() lowerCaseWord = strlower(tempWord)
classMatch = CC:GetCacheTable()[E.myrealm][tempWord] classMatch = CC:GetCacheTable()[E.myrealm][tempWord]
wordMatch = classMatch and lowerCaseWord wordMatch = classMatch and lowerCaseWord
if wordMatch and not E.global.chat.classColorMentionExcludedNames[wordMatch] then if wordMatch and not E.global.chat.classColorMentionExcludedNames[wordMatch] then
classColorTable = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[classMatch] or RAID_CLASS_COLORS[classMatch] classColorTable = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[classMatch] or RAID_CLASS_COLORS[classMatch]
word = word:gsub(tempWord:gsub("%-","%%-"), format("\124cff%.2x%.2x%.2x%s\124r", classColorTable.r*255, classColorTable.g*255, classColorTable.b*255, tempWord)) word = gsub(word, gsub(tempWord, "%-","%%-"), format("\124cff%.2x%.2x%.2x%s\124r", classColorTable.r*255, classColorTable.g*255, classColorTable.b*255, tempWord))
end end
if not isFirstWord then if not isFirstWord then
@@ -1,13 +1,15 @@
local E, L, V, P, G = unpack(ElvUI) local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local mod = E:NewModule("NamePlates", "AceHook-3.0", "AceEvent-3.0", "AceTimer-3.0") local mod = E:NewModule("NamePlates", "AceHook-3.0", "AceEvent-3.0", "AceTimer-3.0");
--local CC = E:GetModule("ClassCache") local CC = E:GetModule("ClassCache");
--Cache global variables
--Lua functions
local _G = _G local _G = _G
local pairs, tonumber = pairs, tonumber local pairs, tonumber = pairs, tonumber
local select = select local select = select
local gsub, match, split = string.gsub, string.match, string.split local gsub, match, split = string.gsub, string.match, string.split
local twipe = table.wipe local twipe = table.wipe
--WoW API / Variables
local CreateFrame = CreateFrame local CreateFrame = CreateFrame
local GetBattlefieldScore = GetBattlefieldScore local GetBattlefieldScore = GetBattlefieldScore
local GetNumBattlefieldScores = GetNumBattlefieldScores local GetNumBattlefieldScores = GetNumBattlefieldScores
@@ -21,7 +23,7 @@ local WorldGetNumChildren, WorldGetChildren = WorldFrame.GetNumChildren, WorldFr
local numChildren = 0 local numChildren = 0
local isTarget = false local isTarget = false
local BORDER = "Interface\\Tooltips\\Nameplate-Border" local BORDER = "Interface\\Tooltips\\Nameplate-Border"
local FSPAT = "%s*" local FSPAT = "^%s*$"
local queryList = {} local queryList = {}
local RaidIconCoordinate = { local RaidIconCoordinate = {
@@ -269,21 +271,21 @@ function mod:RoundColors(r, g, b)
end end
function mod:UnitClass(name, type) function mod:UnitClass(name, type)
if E.private.general.classCache then --[[if E.private.general.classCache then
if type == "FRIENDLY_PLAYER" then if type == "FRIENDLY_PLAYER" then
local _, class = UnitClass(name) local _, class = UnitClass(name)
if class then if class then
return class return class
else else
local name, realm = split("-", name) local name, realm = split("-", name)
--return CC:GetClassByName(name, realm) return CC:GetClassByName(name, realm)
end end
end end
else else
if type == "FRIENDLY_PLAYER" then if type == "FRIENDLY_PLAYER" then
--return select(2, UnitClass(name)) return select(2, UnitClass(name))
end end
end end--]]
end end
function mod:UnitDetailedThreatSituation(frame) function mod:UnitDetailedThreatSituation(frame)
@@ -300,7 +302,7 @@ function mod:UnitLevel(frame)
end end
function mod:GetUnitInfo(frame) function mod:GetUnitInfo(frame)
--[[if UnitExists("target") == 1 and frame:GetParent():IsShown() and frame:GetParent():GetAlpha() == 1 then if UnitExists("target") == 1 and frame:GetParent():IsShown() and frame:GetParent():GetAlpha() == 1 then
if UnitIsPlayer("target") then if UnitIsPlayer("target") then
if UnitIsEnemy("target", "player") then if UnitIsEnemy("target", "player") then
return 2, "ENEMY_PLAYER" return 2, "ENEMY_PLAYER"
@@ -316,7 +318,7 @@ function mod:GetUnitInfo(frame)
return 5, "FRIENDLY_NPC" return 5, "FRIENDLY_NPC"
end end
end end
end]] end
local r, g, b = mod:RoundColors(frame.oldHealthBar:GetStatusBarColor()) local r, g, b = mod:RoundColors(frame.oldHealthBar:GetStatusBarColor())
if r == 1 and g == 0 and b == 0 then if r == 1 and g == 0 and b == 0 then
@@ -708,7 +710,7 @@ function mod:PLAYER_REGEN_ENABLED()
end end
end end
--[[function mod:ClassCacheQueryResult(_, name, class) function mod:ClassCacheQueryResult(_, name, class)
if queryList[name] then if queryList[name] then
local frame = queryList[name] local frame = queryList[name]
@@ -726,7 +728,7 @@ end
queryList[name] = nil queryList[name] = nil
end end
end]] end
function mod:Initialize() function mod:Initialize()
self.db = E.db["nameplates"] self.db = E.db["nameplates"]
@@ -744,7 +746,7 @@ function mod:Initialize()
--self:RegisterEvent("UNIT_AURA") --self:RegisterEvent("UNIT_AURA")
--self:RegisterEvent("PLAYER_COMBO_POINTS") --self:RegisterEvent("PLAYER_COMBO_POINTS")
--self:RegisterMessage("ClassCacheQueryResult") self:RegisterMessage("ClassCacheQueryResult")
E.NamePlates = self E.NamePlates = self
end end
+10
View File
@@ -15,6 +15,16 @@ G["general"] = {
["versionCheck"] = true ["versionCheck"] = true
} }
G["classCache"] = {}
G["classtimer"] = {}
G["nameplates"] = {}
G["chat"] = {
["classColorMentionExcludedNames"] = {}
}
G["bags"] = { G["bags"] = {
["ignoredItems"] = {} ["ignoredItems"] = {}
} }
+2
View File
@@ -21,6 +21,8 @@ V["general"] = {
["hideCalendar"] = true, ["hideCalendar"] = true,
["zoomLevel"] = 0, ["zoomLevel"] = 0,
}, },
["classCache"] = true,
["classColorMentionsSpeech"] = true,
} }
V["bags"] = { V["bags"] = {
+3
View File
@@ -28,6 +28,9 @@ P["general"] = {
["backdropfadecolor"] = {r = .06, g = .06, b = .06, a = 0.8}, ["backdropfadecolor"] = {r = .06, g = .06, b = .06, a = 0.8},
["valuecolor"] = {r = 254/255, g = 123/255, b = 44/255}, ["valuecolor"] = {r = 254/255, g = 123/255, b = 44/255},
["classCacheStoreInDB"] = true,
["classCacheRequestInfo"] = false,
["minimap"] = { ["minimap"] = {
["size"] = 176, ["size"] = 176,
["locationText"] = "MOUSEOVER", ["locationText"] = "MOUSEOVER",
+61 -1
View File
@@ -1,4 +1,5 @@
local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local CC = E:GetModule("ClassCache");
E.Options.args.general = { E.Options.args.general = {
type = "group", type = "group",
@@ -208,7 +209,66 @@ E.Options.args.general = {
min = 0, max = 4, step = 1, min = 0, max = 4, step = 1,
get = function(info) return E.db.general.decimalLength end, get = function(info) return E.db.general.decimalLength end,
set = function(info, value) E.db.general.decimalLength = value; E:StaticPopup_Show("GLOBAL_RL") end set = function(info, value) E.db.general.decimalLength = value; E:StaticPopup_Show("GLOBAL_RL") end
} },
classCacheHeader = {
order = 51,
type = "header",
name = L["Class Cache"]
},
classCacheEnable = {
order = 52,
type = "toggle",
name = L["Enable"],
desc = L["Enable class caching to colorize names in chat and nameplates."],
get = function(info) return E.private.general.classCache end,
set = function(info, value)
E.private.general.classCache = value
CC:ToggleModule()
end
},
classCacheStoreInDB = {
order = 53,
type = "toggle",
name = L["Store cache in DB"],
desc = L["If cache stored in DB it will be available between game sessions but increase memory usage.\nIn other way it will be wiped on relog or UI reload."],
get = function(info) return E.db.general.classCacheStoreInDB end,
set = function(info, value)
E.db.general.classCacheStoreInDB = value
CC:SwitchCacheType()
end,
disabled = function() return not E.private.general.classCache end
},
classCacheRequestInfo = {
order = 54,
type = "toggle",
name = L["Request info for class cache"],
desc = L["Use LibWho to cache class info"],
get = function(info) return E.db.general.classCacheRequestInfo end,
set = function(info, value)
E.db.general.classCacheRequestInfo = value
end,
disabled = function() return not E.private.general.classCache end
},
wipeClassCacheGlobal = {
order = 55,
type = "execute",
name = L["Wipe DB Cache"],
func = function()
CC:WipeCache(true)
GameTooltip:Hide()
end,
disabled = function() return not CC:GetCacheSize(true) end
},
wipeClassCacheLocal = {
order = 56,
type = "execute",
name = L["Wipe Session Cache"],
func = function()
CC:WipeCache()
GameTooltip:Hide()
end,
disabled = function() return not CC:GetCacheSize() end
}
} }
}, },
media = { media = {
@@ -310,6 +310,16 @@ Or for most users it would be easier to simply put a tga file into your WoW fold
对多数玩家来说, 较简易的方式是将 tga 档放入 WoW 资料夹中, 然后在此处输入档案名称.]] 对多数玩家来说, 较简易的方式是将 tga 档放入 WoW 资料夹中, 然后在此处输入档案名称.]]
--Class Cache
L["Class Cache"] = true;
L["Enable class caching to colorize names in chat and nameplates."] = true;
L["If cache stored in DB it will be available between game sessions but increase memory usage.\nIn other way it will be wiped on relog or UI reload."] = true;
L["Request info for class cache"] = true;
L["Store cache in DB"] = true;
L["Use LibWho to cache class info"] = true;
L["Wipe DB Cache"] = true;
L["Wipe Session Cache"] = true;
--Credits --Credits
L["Coding:"] = "编码:" L["Coding:"] = "编码:"
L["Credits"] = "呜谢" L["Credits"] = "呜谢"
@@ -299,6 +299,16 @@ Example: Interface\AddOns\ElvUI\media\textures\copy
Or for most users it would be easier to simply put a tga file into your WoW folder, then type the name of the file here.]] ] = true; Or for most users it would be easier to simply put a tga file into your WoW folder, then type the name of the file here.]] ] = true;
--Class Cache
L["Class Cache"] = true;
L["Enable class caching to colorize names in chat and nameplates."] = true;
L["If cache stored in DB it will be available between game sessions but increase memory usage.\nIn other way it will be wiped on relog or UI reload."] = true;
L["Request info for class cache"] = true;
L["Store cache in DB"] = true;
L["Use LibWho to cache class info"] = true;
L["Wipe DB Cache"] = true;
L["Wipe Session Cache"] = true;
--Credits --Credits
L["Coding:"] = true; L["Coding:"] = true;
L["Credits"] = true; L["Credits"] = true;
@@ -310,6 +310,16 @@ Exemple: Interface\AddOns\ElvUI\media\textures\copy
Ou pour la majorité des utilsateurs, il serait plus simple de mettre le fichier tga dans le dossier de World of Warcraft puis de taper son nom ici.]] Ou pour la majorité des utilsateurs, il serait plus simple de mettre le fichier tga dans le dossier de World of Warcraft puis de taper son nom ici.]]
--Class Cache
L["Class Cache"] = true;
L["Enable class caching to colorize names in chat and nameplates."] = true;
L["If cache stored in DB it will be available between game sessions but increase memory usage.\nIn other way it will be wiped on relog or UI reload."] = true;
L["Request info for class cache"] = true;
L["Store cache in DB"] = true;
L["Use LibWho to cache class info"] = true;
L["Wipe DB Cache"] = true;
L["Wipe Session Cache"] = true;
--Credits --Credits
L["Coding:"] = "Codage: " L["Coding:"] = "Codage: "
L["Credits"] = "Crédits" L["Credits"] = "Crédits"
@@ -310,6 +310,16 @@ Zum Beispiel: Interface\AddOns\ElvUI\media\textures\copy
Für die meisten Anwender ist es allerdigns einfacher, eine tga-Datei in ihren WoW-Ordner abzulegen. Anschließend kann man den Namen der Datei hier eingeben.]] Für die meisten Anwender ist es allerdigns einfacher, eine tga-Datei in ihren WoW-Ordner abzulegen. Anschließend kann man den Namen der Datei hier eingeben.]]
--Class Cache
L["Class Cache"] = true;
L["Enable class caching to colorize names in chat and nameplates."] = true;
L["If cache stored in DB it will be available between game sessions but increase memory usage.\nIn other way it will be wiped on relog or UI reload."] = true;
L["Request info for class cache"] = true;
L["Store cache in DB"] = true;
L["Use LibWho to cache class info"] = true;
L["Wipe DB Cache"] = true;
L["Wipe Session Cache"] = true;
--Credits --Credits
L["Coding:"] = "Programmierung:" L["Coding:"] = "Programmierung:"
L["Credits"] = "Danksagung" L["Credits"] = "Danksagung"
@@ -358,6 +358,16 @@ Or for most users it would be easier to simply put a tga file into your WoW fold
.]] .]]
--Class Cache
L["Class Cache"] = true;
L["Enable class caching to colorize names in chat and nameplates."] = true;
L["If cache stored in DB it will be available between game sessions but increase memory usage.\nIn other way it will be wiped on relog or UI reload."] = true;
L["Request info for class cache"] = true;
L["Store cache in DB"] = true;
L["Use LibWho to cache class info"] = true;
L["Wipe DB Cache"] = true;
L["Wipe Session Cache"] = true;
--Credits --Credits
L["Coding:"] = "|cff2eb7e4< 개발자 >|r" L["Coding:"] = "|cff2eb7e4< 개발자 >|r"
L["Credits"] = "제작자" L["Credits"] = "제작자"
@@ -310,6 +310,16 @@ Example: Interface\AddOns\ElvUI\media\textures\copy
Para a maioria dos usuários seria mais fácil simplesmente copiar o ficheiro tga na pasta do WoW e depois escrever o nome dele aqui.]] Para a maioria dos usuários seria mais fácil simplesmente copiar o ficheiro tga na pasta do WoW e depois escrever o nome dele aqui.]]
--Class Cache
L["Class Cache"] = true;
L["Enable class caching to colorize names in chat and nameplates."] = true;
L["If cache stored in DB it will be available between game sessions but increase memory usage.\nIn other way it will be wiped on relog or UI reload."] = true;
L["Request info for class cache"] = true;
L["Store cache in DB"] = true;
L["Use LibWho to cache class info"] = true;
L["Wipe DB Cache"] = true;
L["Wipe Session Cache"] = true;
--Credits --Credits
L["Coding:"] = "Codificação:" L["Coding:"] = "Codificação:"
L["Credits"] = "Créditos" L["Credits"] = "Créditos"
@@ -310,6 +310,16 @@ Or for most users it would be easier to simply put a tga file into your WoW fold
Для большинства пользователей будет легче просто положить tga файл в папку игры, а затем написать имя файла здесь.]] Для большинства пользователей будет легче просто положить tga файл в папку игры, а затем написать имя файла здесь.]]
--Class Cache
L["Class Cache"] = true;
L["Enable class caching to colorize names in chat and nameplates."] = true;
L["If cache stored in DB it will be available between game sessions but increase memory usage.\nIn other way it will be wiped on relog or UI reload."] = true;
L["Request info for class cache"] = true;
L["Store cache in DB"] = true;
L["Use LibWho to cache class info"] = true;
L["Wipe DB Cache"] = true;
L["Wipe Session Cache"] = true;
--Credits --Credits
L["Coding:"] = "Написание кода:" L["Coding:"] = "Написание кода:"
L["Credits"] = "Благодарности" L["Credits"] = "Благодарности"
@@ -310,6 +310,16 @@ Ejemplo: Interface\AddOns\ElvUI\media\textures\copy
O también puedes simplemente colocar un archivo tga en la carpeta de WoW, y escribir aquí el nombre del archivo.]] O también puedes simplemente colocar un archivo tga en la carpeta de WoW, y escribir aquí el nombre del archivo.]]
--Class Cache
L["Class Cache"] = true;
L["Enable class caching to colorize names in chat and nameplates."] = true;
L["If cache stored in DB it will be available between game sessions but increase memory usage.\nIn other way it will be wiped on relog or UI reload."] = true;
L["Request info for class cache"] = true;
L["Store cache in DB"] = true;
L["Use LibWho to cache class info"] = true;
L["Wipe DB Cache"] = true;
L["Wipe Session Cache"] = true;
--Credits --Credits
L["Coding:"] = "Codificación:" L["Coding:"] = "Codificación:"
L["Credits"] = "Créditos" L["Credits"] = "Créditos"
@@ -310,6 +310,16 @@ Or for most users it would be easier to simply put a tga file into your WoW fold
, tga WoW , .]] , tga WoW , .]]
--Class Cache
L["Class Cache"] = true;
L["Enable class caching to colorize names in chat and nameplates."] = true;
L["If cache stored in DB it will be available between game sessions but increase memory usage.\nIn other way it will be wiped on relog or UI reload."] = true;
L["Request info for class cache"] = true;
L["Store cache in DB"] = true;
L["Use LibWho to cache class info"] = true;
L["Wipe DB Cache"] = true;
L["Wipe Session Cache"] = true;
--Credits --Credits
L["Coding:"] = "編碼:" L["Coding:"] = "編碼:"
L["Credits"] = "嗚謝" L["Credits"] = "嗚謝"