enUS Localization Update Announcement / localization-update-announcement (push) Canceled after 0s
510 lines
14 KiB
Lua
510 lines
14 KiB
Lua
local vmajor, vminor = "1", tonumber(string.sub("$Revision: 15062 $", 12, -3))
|
|
|
|
-- lua 5.1 check
|
|
if not loadstring("return function(...) return ... end") and true or false then
|
|
string.gmatch = string.gfind
|
|
end
|
|
|
|
-- Check to see if an update is needed
|
|
-- if not then just return out now before we do anything
|
|
local libobj = PeriodicTableEmbed
|
|
if libobj and not libobj:NeedsUpgraded(vmajor, vminor) then
|
|
return
|
|
end
|
|
|
|
local stubobj = TekLibStub
|
|
if not stubobj then
|
|
stubobj = {}
|
|
TekLibStub = stubobj
|
|
|
|
-- Instance replacement method, replace contents of old with that of new
|
|
function stubobj:ReplaceInstance(old, new)
|
|
for k, v in pairs(old) do
|
|
old[k] = nil
|
|
end
|
|
for k, v in pairs(new) do
|
|
old[k] = v
|
|
end
|
|
end
|
|
|
|
-- Get a new copy of the stub
|
|
function stubobj:NewStub(name)
|
|
local newStub = {}
|
|
self:ReplaceInstance(newStub, self)
|
|
newStub.libName = name
|
|
newStub.lastVersion = ""
|
|
newStub.versions = {}
|
|
return newStub
|
|
end
|
|
|
|
-- Get instance version
|
|
function stubobj:NeedsUpgraded(vmajor, vminor)
|
|
local versionData = self.versions[vmajor]
|
|
if not versionData or versionData.minor < vminor then
|
|
return true
|
|
end
|
|
end
|
|
|
|
-- Get instance version
|
|
function stubobj:GetInstance(version)
|
|
if not version then
|
|
version = self.lastVersion
|
|
end
|
|
local versionData = self.versions[version]
|
|
if not versionData then
|
|
print(string.format("<%s> Cannot find library version: %s", self.libName, version or ""))
|
|
return
|
|
end
|
|
return versionData.instance
|
|
end
|
|
|
|
-- Register new instance
|
|
function stubobj:Register(newInstance)
|
|
local version, minor = newInstance:GetLibraryVersion()
|
|
self.lastVersion = version
|
|
local versionData = self.versions[version]
|
|
if not versionData then
|
|
-- This one is new!
|
|
versionData = {
|
|
instance = newInstance,
|
|
minor = minor,
|
|
old = {},
|
|
}
|
|
self.versions[version] = versionData
|
|
newInstance:LibActivate(self)
|
|
return newInstance
|
|
end
|
|
-- This is an update
|
|
local oldInstance = versionData.instance
|
|
local oldList = versionData.old
|
|
versionData.instance = newInstance
|
|
versionData.minor = minor
|
|
local skipCopy = newInstance:LibActivate(self, oldInstance, oldList)
|
|
table.insert(oldList, oldInstance)
|
|
if not skipCopy then
|
|
for i, old in ipairs(oldList) do
|
|
self:ReplaceInstance(old, newInstance)
|
|
end
|
|
end
|
|
return newInstance
|
|
end
|
|
end
|
|
|
|
if not libobj then
|
|
libobj = stubobj:NewStub("PeriodicTableEmbed")
|
|
PeriodicTableEmbed = libobj
|
|
end
|
|
|
|
local lib = {}
|
|
|
|
-- Return the library's current version
|
|
function lib:GetLibraryVersion()
|
|
return vmajor, vminor
|
|
end
|
|
|
|
-- Activate a new instance of this library
|
|
function lib:LibActivate(stub, oldLib, oldList)
|
|
local maj, min = self:GetLibraryVersion()
|
|
|
|
if oldLib then
|
|
local omaj, omin = oldLib:GetLibraryVersion()
|
|
self.vars, self.k, self.loadstats = oldLib.vars, oldLib.k, oldLib.loadstats
|
|
else
|
|
self.vars = { numcustoms = 0 }
|
|
self.k, self.loadstats = {}, {}
|
|
end
|
|
self.compost = AceLibrary and AceLibrary:HasInstance("Compost-2.0") and AceLibrary("Compost-2.0")
|
|
-- nil return makes stub do object copy
|
|
end
|
|
|
|
-----------------------------------------------------------------
|
|
-- *********************************************************** --
|
|
-- ** Everything in this section is internal code ** --
|
|
-- ** please see the API section for external use ** --
|
|
-- *********************************************************** --
|
|
-----------------------------------------------------------------
|
|
|
|
function lib:Print(a1, a2, a3, a4, a5)
|
|
if not a1 then
|
|
return
|
|
end
|
|
ChatFrame1:AddMessage("|cffffff78Periodic Table: |r" .. string.format(a1, a2, a3, a4, a5))
|
|
end
|
|
|
|
-- Called internally, you probably shouldn't be calling it directly, but hey do what you want :P
|
|
function lib:CacheSet(set)
|
|
if not set then
|
|
return
|
|
end
|
|
|
|
local rset = self:GetSet(set)
|
|
if not rset or type(rset) ~= "string" then
|
|
return
|
|
end
|
|
|
|
if not self.vars.cache then
|
|
self.vars.cache = {}
|
|
end
|
|
if not self.vars.cache[set] then
|
|
self.vars.cache[set] = {}
|
|
for word in string.gmatch(rset, "%S+") do
|
|
local _, _, id, val = string.find(word, "(%d+):(%d+)")
|
|
id, val = tonumber(id) or tonumber(word), tonumber(val) or 0
|
|
self.vars.cache[set][id] = val
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function lib:GetID(item)
|
|
if type(item) == "number" then
|
|
return item
|
|
elseif type(item) == "string" then
|
|
local _, _, id = string.find(item, "item:(%d+):%d+:%d+:%d+")
|
|
if id then
|
|
return tonumber(id)
|
|
end
|
|
end
|
|
end
|
|
|
|
function lib:GetSet(set)
|
|
if not set then
|
|
return
|
|
end
|
|
for i, vals in pairs(self.k) do
|
|
if vals[set] then
|
|
return vals[set]
|
|
end
|
|
end
|
|
end
|
|
|
|
function lib:GetSetModule(set)
|
|
if not set then
|
|
return
|
|
end
|
|
for i, vals in pairs(self.k) do
|
|
if vals[set] then
|
|
return i
|
|
end
|
|
end
|
|
end
|
|
|
|
function lib:GetSetString(set)
|
|
if type(set) == "string" then
|
|
return
|
|
elseif type(set) == "table" then
|
|
local retval
|
|
for i, val in pairs(set) do
|
|
if type(i) == "number" then
|
|
local valstr = (val > 0) and string.format("%s:%s", i, val) or tostring(i)
|
|
retval = retval and string.format("%s %s", retval, valstr) or valstr
|
|
end
|
|
end
|
|
|
|
return retval
|
|
end
|
|
end
|
|
|
|
function lib:CreateTrashTable(set, bosses)
|
|
local retval, t = {}, self:GetSetTable(set)
|
|
if not t then
|
|
return
|
|
end
|
|
for i, v in pairs(t) do
|
|
if not self:ItemInSet(i, bosses) then
|
|
retval[i] = v
|
|
end
|
|
end
|
|
return self:GetSetString(retval)
|
|
end
|
|
|
|
function lib:FindWorldDrops()
|
|
local t, retval = {}, {}
|
|
for _, set in self.k["Instance Loot"].instancezones do
|
|
t = self:MergeSetToTable(t, set)
|
|
end
|
|
for _, set in self.k["Raid Loot"].raidzones do
|
|
t = self:MergeSetToTable(t, set)
|
|
end
|
|
for item, val in t do
|
|
if val > 1 then
|
|
retval[item] = val
|
|
end
|
|
end
|
|
return self:GetSetString(retval)
|
|
end
|
|
|
|
function lib:MergeSetToTable(table, set)
|
|
local t = self:GetSetTable(set)
|
|
if t then
|
|
for item, val in t do
|
|
if table[item] then
|
|
table[item] = table[item] + 1
|
|
else
|
|
table[item] = 1
|
|
end
|
|
end
|
|
end
|
|
return table
|
|
end
|
|
|
|
function lib:RemoveAllWorldDrops()
|
|
local retval = { instancezones = {}, raidzones = {}, instancebosses = {}, raidbosses = {} }
|
|
for _, set in self.k["Instance Loot"].instancezones do
|
|
retval.instancezones[set] = self:RemoveWorldDrops(set)
|
|
end
|
|
for _, set in self.k["Raid Loot"].raidzones do
|
|
retval.raidzones[set] = self:RemoveWorldDrops(set)
|
|
end
|
|
for _, set in self.k["Instance Loot"].instancebosses do
|
|
retval.instancebosses[set] = self:RemoveWorldDrops(set)
|
|
end
|
|
for _, set in self.k["Raid Loot"].raidbosses do
|
|
retval.raidbosses[set] = self:RemoveWorldDrops(set)
|
|
end
|
|
return retval
|
|
end
|
|
|
|
function lib:RemoveWorldDrops(set)
|
|
local t = self:GetSetTable(set)
|
|
if t then
|
|
local retval = ""
|
|
for item, val in t do
|
|
if not self:ItemInSet(item, { "worlddrops", "bossdrops", "NOTworlddrops" }) then
|
|
local v = item .. (val > 0 and (":" .. val) or "")
|
|
if retval == "" then
|
|
retval = v
|
|
else
|
|
retval = retval .. " " .. v
|
|
end
|
|
end
|
|
end
|
|
|
|
return retval
|
|
end
|
|
end
|
|
|
|
-----------------------------
|
|
-- Module Loadup --
|
|
-----------------------------
|
|
|
|
function lib:AddModule(name, table, memory)
|
|
if not name or not table or not memory then
|
|
return
|
|
end
|
|
if self.k[name] and self.compost then
|
|
self.compost:Reclaim(self.k[name])
|
|
end
|
|
self.k[name] = table
|
|
self.loadstats[name] = self.loadstats[name] or 0 + memory
|
|
self.vars.cache = {}
|
|
end
|
|
|
|
---------------------------------
|
|
-- *************************** --
|
|
-- ** API Section ** --
|
|
-- *************************** --
|
|
---------------------------------
|
|
|
|
-- item: ItemID (a number) or ItemLink (a string)
|
|
-- set: set to check (a string) or sets to check (a table of strings)
|
|
-- returns: value (a number) ~~~ 0 indicates no value defined
|
|
-- set (a string) ~~~ the set that the item was found in
|
|
-- *** it is up to you to make sure all sets passed share a common value, the first matching value is returned!
|
|
function lib:ItemInSet(item, set)
|
|
local item = self:GetID(item)
|
|
if not item then
|
|
return
|
|
end
|
|
|
|
if type(set) == "string" then
|
|
local rset = self:GetSet(set)
|
|
if rset and type(rset) == "string" then
|
|
local t = self:GetSetTable(set)
|
|
if t and t[item] then
|
|
return t[item], set, set
|
|
end
|
|
elseif type(rset) == "table" then
|
|
for _, s in rset do
|
|
local retval, _, atom = self:ItemInSet(item, s)
|
|
if retval then
|
|
return retval, s, atom
|
|
end
|
|
end
|
|
end
|
|
elseif type(set) == "table" then
|
|
for i, s in pairs(set) do
|
|
local retval, _, atom = self:ItemInSet(item, s)
|
|
if retval then
|
|
return retval, s, atom
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- item: ItemID (a number) or ItemLink (a string)
|
|
-- sets: sets to check (a table of strings)
|
|
-- returns: a table of the sets found, or nil if not found
|
|
-- ** key difference between this and ItemInSet, this wil check for every match
|
|
-- ** ItemInSet will just return the first one found. Also this func does not return the numeric values
|
|
function lib:ItemInSets(item, sets)
|
|
local item = self:GetID(item)
|
|
if not item then
|
|
return
|
|
end
|
|
|
|
if type(sets) == "string" then
|
|
local rset = self:GetSet(sets)
|
|
if type(rset) == "string" then
|
|
local inset = self:ItemInSet(item, sets)
|
|
if inset then
|
|
return self.compost and self.compost:Acquire(sets) or { sets }
|
|
end
|
|
elseif type(rset) == "table" then
|
|
return self:ItemInSets(item, rset)
|
|
end
|
|
elseif type(sets) == "table" then
|
|
local founds
|
|
|
|
for i, s in pairs(sets) do
|
|
if self:ItemInSet(item, s) then
|
|
if not founds then
|
|
founds = self.compost and self.compost:Acquire() or {}
|
|
end
|
|
table.insert(founds, s)
|
|
end
|
|
end
|
|
|
|
return founds
|
|
end
|
|
end
|
|
|
|
local iterbag, iterslot, iterset
|
|
local iter = function()
|
|
if iterslot > GetContainerNumSlots(iterbag) then
|
|
iterbag, iterslot = iterbag + 1, 1
|
|
end
|
|
if iterbag > 4 then
|
|
return
|
|
end
|
|
|
|
for b = iterbag, 4 do
|
|
for s = iterslot, GetContainerNumSlots(b) do
|
|
iterslot = s + 1
|
|
|
|
local link = GetContainerItemLink(b, s)
|
|
local val = link and lib:ItemInSet(link, iterset)
|
|
if val then
|
|
return b, s, val
|
|
end
|
|
end
|
|
|
|
iterbag, iterslot = b + 1, 1
|
|
end
|
|
end
|
|
|
|
-- Iterator for scanning bags for set matches
|
|
-- Returns back bag, slot, value
|
|
function lib:BagIter(set)
|
|
if not set then
|
|
return
|
|
end
|
|
|
|
iterbag, iterslot, iterset = 0, 1, set
|
|
return iter
|
|
end
|
|
|
|
-- Returns the bag/slot of the "best" item in the set,
|
|
-- if there are two "matching" items the first one in your bags is returned
|
|
-- By default this will just compare PT values, however, if comparefunc is passed this will be used as the evaluation function
|
|
-- Args:
|
|
-- set - the set you wish to match
|
|
-- comparefunc(optional) - a function to test two items against each other
|
|
-- this function must take 6 args (item1_bag, item1_slot, item1_value, item2_bag, item2_slot, item2_value)
|
|
-- and should return true if item1 is "better" than item2
|
|
-- validatefunc (optional) - a function to check an item with, if it returns false/nil the item isn't used
|
|
-- Ideal for checking that an item is "good enough" or not too high of value
|
|
-- Returns: Bag, Slot and PT Value of best match, if a match is found
|
|
local defaultcomparefunc = function(abag, aslot, aval, bbag, bslot, bval)
|
|
return aval > bval
|
|
end
|
|
local defaultvalidatefunc = function(bag, slot, val)
|
|
return true
|
|
end
|
|
function lib:GetBest(set, comparefunc, validatefunc)
|
|
comparefunc = comparefunc or defaultcomparefunc
|
|
validatefunc = validatefunc or defaultvalidatefunc
|
|
local ibag, islot, ival
|
|
|
|
for bag, slot, val in self:BagIter(set) do
|
|
if validatefunc(bag, slot, val) and (not ival or comparefunc(bag, slot, val, ibag, islot, ival)) then
|
|
ibag, islot, ival = bag, slot, val
|
|
end
|
|
end
|
|
return ibag, islot, ival
|
|
end
|
|
|
|
-- Returns a reference to the set specified's expanded table
|
|
-- this is the table in the cache so don't go erasing it or anything!
|
|
-- **** This only works for atomic sets, not multisets ****
|
|
function lib:GetSetTable(set)
|
|
if self:CacheSet(set) then
|
|
return self.vars.cache[set]
|
|
end
|
|
end
|
|
|
|
-- Register a custom set
|
|
-- Args:
|
|
-- setcode (a string) - must be space-delimited itemid's of the format below
|
|
-- name (an optional string) - the name of the set
|
|
-- setcode format:
|
|
-- int or int:int where the first or only int is itemid, the second is a relative value
|
|
-- the relative value can be anything you wish, it is intended to aid in sorting
|
|
-- if the item's level isn't enough
|
|
-- Returns a string, the index/setname of your set, or nil if that setname already exists
|
|
function lib:RegisterCustomSet(setcode, name)
|
|
local setname = name or "customset" .. self.vars.numcustoms
|
|
if not setcode then
|
|
return
|
|
end
|
|
if self:GetSetModule(setname) then
|
|
return
|
|
end
|
|
|
|
self.k.customsets = self.k.customsets or {}
|
|
self.k.customsets[setname] = setcode
|
|
if not name then
|
|
self.vars.numcustoms = self.vars.numcustoms + 1
|
|
end
|
|
return setname
|
|
end
|
|
|
|
-- Loads up every module, dumps the memory used and time taken by each to chat
|
|
function lib:Benchmark()
|
|
self.vars.cache = {}
|
|
collectgarbage()
|
|
|
|
local loadsize, tt, tmem = 0, GetTime(), gcinfo()
|
|
for i, vals in self.k do
|
|
local t, mem = GetTime(), gcinfo()
|
|
for j, v in vals do
|
|
if type(v) == "string" then
|
|
self:CacheSet(j)
|
|
end
|
|
end
|
|
|
|
local compsize = self.loadstats[i] or 0
|
|
loadsize = loadsize + compsize
|
|
t, mem = (GetTime() - t), (gcinfo() - mem)
|
|
self:Print("|cff80ff80%d ms|r %s set |cffff8000(%d --> %d KiB)", t * 1000, i, compsize, mem)
|
|
end
|
|
tt, tmem = (GetTime() - tt), (gcinfo() - tmem)
|
|
self:Print("|cff80ff80%d ms|r All sets |cffff8000(%d --> %d KiB)", tt * 1000, loadsize, tmem)
|
|
end
|
|
|
|
--------------------------------
|
|
-- Load this bitch! --
|
|
--------------------------------
|
|
libobj:Register(lib)
|