vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1  
2 local vmajor, vminor = "1", tonumber(string.sub("$Revision: 2219 $", 12, -3))
3  
4  
5 -- Check to see if an update is needed
6 -- if not then just return out now before we do anything
7 local libobj = PeriodicTableEmbed
8 if libobj and not libobj:NeedsUpgraded(vmajor, vminor) then return end
9  
10  
11 local stubobj = TekLibStub
12 if not stubobj then
13 stubobj = {}
14 TekLibStub = stubobj
15  
16  
17 -- Instance replacement method, replace contents of old with that of new
18 function stubobj:ReplaceInstance(old, new)
19 for k,v in pairs(old) do old[k]=nil end
20 for k,v in pairs(new) do old[k]=v end
21 end
22  
23  
24 -- Get a new copy of the stub
25 function stubobj:NewStub(name)
26 local newStub = {}
27 self:ReplaceInstance(newStub, self)
28 newStub.libName = name
29 newStub.lastVersion = ''
30 newStub.versions = {}
31 return newStub
32 end
33  
34  
35 -- Get instance version
36 function stubobj:NeedsUpgraded(vmajor, vminor)
37 local versionData = self.versions[vmajor]
38 if not versionData or versionData.minor < vminor then return true end
39 end
40  
41  
42 -- Get instance version
43 function stubobj:GetInstance(version)
44 if not version then version = self.lastVersion end
45 local versionData = self.versions[version]
46 if not versionData then print(string.format("<%s> Cannot find library version: %s", self.libName, version or "")) return end
47 return versionData.instance
48 end
49  
50  
51 -- Register new instance
52 function stubobj:Register(newInstance)
53 local version,minor = newInstance:GetLibraryVersion()
54 self.lastVersion = version
55 local versionData = self.versions[version]
56 if not versionData then
57 -- This one is new!
58 versionData = {
59 instance = newInstance,
60 minor = minor,
61 old = {},
62 }
63 self.versions[version] = versionData
64 newInstance:LibActivate(self)
65 return newInstance
66 end
67 -- This is an update
68 local oldInstance = versionData.instance
69 local oldList = versionData.old
70 versionData.instance = newInstance
71 versionData.minor = minor
72 local skipCopy = newInstance:LibActivate(self, oldInstance, oldList)
73 table.insert(oldList, oldInstance)
74 if not skipCopy then
75 for i, old in ipairs(oldList) do self:ReplaceInstance(old, newInstance) end
76 end
77 return newInstance
78 end
79 end
80  
81  
82 if not libobj then
83 libobj = stubobj:NewStub("PeriodicTableEmbed")
84 PeriodicTableEmbed = libobj
85 end
86  
87 local lib = {}
88  
89  
90 -- Return the library's current version
91 function lib:GetLibraryVersion()
92 return vmajor, vminor
93 end
94  
95  
96 -- Activate a new instance of this library
97 function lib:LibActivate(stub, oldLib, oldList)
98 local maj, min = self:GetLibraryVersion()
99  
100 if oldLib then
101 local omaj, omin = oldLib:GetLibraryVersion()
102 self.compost = oldLib.compost or CompostLib and CompostLib:GetInstance("compost-1")
103 self.vars, self.k, self.loadstats = oldLib.vars, oldLib.k, oldLib.loadstats
104 else
105 self.vars = {numcustoms = 0}
106 self.k, self.loadstats = {}, {}
107 self.compost = CompostLib and CompostLib:GetInstance("compost-1")
108 end
109 -- nil return makes stub do object copy
110 end
111  
112  
113 -----------------------------------------------------------------
114 -- *********************************************************** --
115 -- ** Everything in this section is internal code ** --
116 -- ** please see the API section for external use ** --
117 -- *********************************************************** --
118 -----------------------------------------------------------------
119  
120  
121 function lib:Print(a1,a2,a3,a4,a5)
122 if not a1 then return end
123 ChatFrame1:AddMessage("|cffffff78Periodic Table: |r"..string.format(a1,a2,a3,a4,a5))
124 end
125  
126  
127 -- Called internally, you probably shouldn't be calling it directly, but hey do what you want :P
128 function lib:CacheSet(set)
129 if not set then return end
130  
131 local rset = self:GetSet(set)
132 if not rset or type(rset) ~= "string" then return end
133  
134 if not self.vars.cache then self.vars.cache = {} end
135 if not self.vars.cache[set] then
136 self.vars.cache[set] = {}
137 for word in gfind(rset, "%S+") do
138 local _, _, id, val = string.find(word, "(%d+):(%d+)")
139 id, val = tonumber(id) or tonumber(word), tonumber(val) or 0
140 self.vars.cache[set][id] = val
141 end
142 end
143  
144 return true
145 end
146  
147  
148 function lib:GetID(item)
149 if type(item) == "number" then return item
150 elseif type(item) == "string" then
151 local _, _, id = string.find(item, "item:(%d+):%d+:%d+:%d+")
152 if id then return tonumber(id) end
153 end
154 end
155  
156  
157 function lib:GetSet(set)
158 if not set then return end
159 for i,vals in pairs(self.k) do if vals[set] then return vals[set] end end
160 end
161  
162  
163 function lib:GetSetModule(set)
164 if not set then return end
165 for i,vals in pairs(self.k) do if vals[set] then return i end end
166 end
167  
168  
169 function lib:GetSetString(set)
170 if type(set) == "string" then
171 return
172 elseif type(set) == "table" then
173 local retval
174 for i,val in pairs(set) do
175 if type(i) == "number" then
176 local valstr = (val > 0) and string.format("%s:%s", i, val) or tostring(i)
177 retval = retval and string.format("%s %s", retval, valstr) or valstr
178 end
179 end
180  
181 return retval
182 end
183 end
184  
185  
186 function lib:CreateTrashTable(set, bosses)
187 local retval, t = {}, self:GetSetTable(set)
188 if not t then return end
189 for i,v in pairs(t) do if not self:ItemInSet(i, bosses) then retval[i] = v end end
190 return self:GetSetString(retval)
191 end
192  
193  
194 function lib:FindWorldDrops()
195 local t, retval = {}, {}
196 for _,set in self.k["Instance Loot"].instancezones do t = self:MergeSetToTable(t, set) end
197 for _,set in self.k["Raid Loot"].raidzones do t = self:MergeSetToTable(t, set) end
198 for item,val in t do if val > 1 then retval[item] = val end end
199 return self:GetSetString(retval)
200 end
201  
202  
203 function lib:MergeSetToTable(table, set)
204 local t = self:GetSetTable(set)
205 if t then
206 for item,val in t do
207 if table[item] then table[item] = table[item] + 1
208 else table[item] = 1 end
209 end
210 end
211 return table
212 end
213  
214  
215 function lib:RemoveAllWorldDrops()
216 local retval = {instancezones = {}, raidzones = {}, instancebosses = {}, raidbosses = {}}
217 for _,set in self.k["Instance Loot"].instancezones do retval.instancezones[set] = self:RemoveWorldDrops(set) end
218 for _,set in self.k["Raid Loot"].raidzones do retval.raidzones[set] = self:RemoveWorldDrops(set) end
219 for _,set in self.k["Instance Loot"].instancebosses do retval.instancebosses[set] = self:RemoveWorldDrops(set) end
220 for _,set in self.k["Raid Loot"].raidbosses do retval.raidbosses[set] = self:RemoveWorldDrops(set) end
221 return retval
222 end
223  
224  
225 function lib:RemoveWorldDrops(set)
226 local t = self:GetSetTable(set)
227 if t then
228 local retval = ""
229 for item,val in t do
230 if not self:ItemInSet(item, {"worlddrops", "bossdrops", "NOTworlddrops"}) then
231 local v = item..(val > 0 and (":"..val) or "")
232 if retval == "" then retval = v else retval = retval.." "..v end
233 end
234 end
235  
236 return retval
237 end
238 end
239  
240  
241 -----------------------------
242 -- Module Loadup --
243 -----------------------------
244  
245 function lib:AddModule(name, table, memory)
246 if not name or not table or not memory then return end
247 if self.k[name] and self.compost then self.compost:Reclaim(self.k[name]) end
248 self.k[name] = table
249 self.loadstats[name] = self.loadstats[name] or 0 + memory
250 end
251  
252  
253 ---------------------------------
254 -- *************************** --
255 -- ** API Section ** --
256 -- *************************** --
257 ---------------------------------
258  
259  
260  
261 -- item: ItemID (a number) or ItemLink (a string)
262 -- set: set to check (a string) or sets to check (a table of strings)
263 -- returns: value (a number) ~~~ 0 indicates no value defined
264 -- set (a string) ~~~ the set that the item was found in
265 -- *** it is up to you to make sure all sets passed share a common value, the first matching value is returned!
266 function lib:ItemInSet(item, set)
267 local item = self:GetID(item)
268 if not item then return end
269  
270 if type(set) == "string" then
271 local rset = self:GetSet(set)
272 if rset and type(rset) == "string" then
273 local t = self:GetSetTable(set)
274 if t and t[item] then return t[item], set end
275 elseif type(rset) == "table" then
276 for _,s in rset do
277 local retval = self:ItemInSet(item, s)
278 if retval then return retval, s end
279 end
280 end
281 elseif type(set) == "table" then
282 for i,s in pairs(set) do
283 local retval = self:ItemInSet(item, s)
284 if retval then return retval, s end
285 end
286 end
287 end
288  
289  
290 -- item: ItemID (a number) or ItemLink (a string)
291 -- sets: sets to check (a table of strings)
292 -- returns: a table of the sets found, or nil if not found
293 -- ** key difference between this and ItemInSet, this wil check for every match
294 -- ** ItemInSet will just return the first one found. Also this func does not return the numeric values
295 function lib:ItemInSets(item, sets)
296 local item = self:GetID(item)
297 if not item then return end
298  
299 if type(sets) == "string" then
300 local rset = self:GetSet(sets)
301 if type(rset) == "string" then
302 local inset = self:ItemInSet(item, sets)
303 if inset then return self.compost and self.compost:Acquire(sets) or {sets} end
304 elseif type(rset) == "table" then
305 return self:ItemInSets(item, rset)
306 end
307 elseif type(sets) == "table" then
308 local founds
309  
310 for i,s in pairs(sets) do
311 if self:ItemInSet(item, s) then
312 if not founds then founds = self.compost and self.compost:Acquire() or {} end
313 table.insert(founds, s)
314 end
315 end
316  
317 return founds
318 end
319 end
320  
321  
322 -- Iterator for scanning bags for set matches
323 -- Returns back bag, slot, value
324 function lib:BagIter(set)
325 if not set then return end
326  
327 local bag, slot = 0, 1
328  
329 return function()
330 if slot > GetContainerNumSlots(bag) then bag, slot = bag + 1, 1 end
331 if bag > 4 then return end
332  
333 for b=bag,4 do
334 for s=slot,GetContainerNumSlots(b) do
335 slot = s + 1
336  
337 local link = GetContainerItemLink(b,s)
338 local val = link and self:ItemInSet(link, set)
339 if val then return b, s, val end
340 end
341  
342 bag, slot = b+1, 1
343 end
344 end
345 end
346  
347  
348 -- Returns the bag/slot of the "best" item in the set,
349 -- if there are two "matching" items the first one in your bags is returned
350 -- By default this will just compare PT values, however, if comparefunc is passed this will be used as the evaluation function
351 -- Args:
352 -- set - the set you wish to match
353 -- comparefunc(optional) - a function to test two items against each other
354 -- this function must take 6 args (item1_bag, item1_slot, item1_value, item2_bag, item2_slot, item2_value)
355 -- and should return true if item1 is "better" than item2
356 -- validatefunc (optional) - a function to check an item with, if it returns false/nil the item isn't used
357 -- Ideal for checking that an item is "good enough" or not too high of value
358 -- Returns: Bag, Slot and PT Value of best match, if a match is found
359 local defaultcomparefunc = function(abag, aslot, aval, bbag, bslot, bval) return aval > bval end
360 local defaultvalidatefunc = function(bag, slot, val) return true end
361 function lib:GetBest(set, comparefunc, validatefunc)
362 comparefunc = comparefunc or defaultcomparefunc
363 validatefunc = validatefunc or defaultvalidatefunc
364 local ibag, islot, ival
365  
366 for bag,slot,val in self:BagIter(set) do
367 if validatefunc(bag,slot,val) and (not ival or comparefunc(bag, slot, val, ibag, islot, ival)) then
368 ibag, islot, ival = bag, slot, val
369 end
370 end
371 return ibag, islot, ival
372 end
373  
374  
375 -- Returns a reference to the set specified's expanded table
376 -- this is the table in the cache so don't go erasing it or anything!
377 -- **** This only works for atomic sets, not multisets ****
378 function lib:GetSetTable(set)
379 if self:CacheSet(set) then return self.vars.cache[set] end
380 end
381  
382  
383 -- Register a custom set
384 -- Args:
385 -- setcode (a string) - must be space-delimited itemid's of the format below
386 -- name (an optional string) - the name of the set
387 -- setcode format:
388 -- int or int:int where the first or only int is itemid, the second is a relative value
389 -- the relative value can be anything you wish, it is intended to aid in sorting
390 -- if the item's level isn't enough
391 -- Returns a string, the index/setname of your set, or nil if that setname already exists
392 function lib:RegisterCustomSet(setcode, name)
393 local setname = name or "customset"..self.vars.numcustoms
394 if not setcode then return end
395 if self:GetSetModule(setname) then return end
396  
397 self.k.customsets = self.k.customsets or {}
398 self.k.customsets[setname] = setcode
399 if not name then self.vars.numcustoms = self.vars.numcustoms + 1 end
400 return setname
401 end
402  
403  
404 -- Loads up every module, dumps the memory used and time taken by each to chat
405 function lib:Benchmark()
406 self.vars.cache = {}
407 collectgarbage()
408  
409 local loadsize, tt, tmem = 0, GetTime(), gcinfo()
410 for i,vals in self.k do
411 local t, mem = GetTime(), gcinfo()
412 for j,v in vals do
413 if (type(v) == "string") then self:CacheSet(j) end
414 end
415  
416 local compsize = self.loadstats[i] or 0
417 loadsize = loadsize + compsize
418 t, mem = (GetTime() - t), (gcinfo() - mem)
419 self:Print("|cff80ff80%d ms|r %s set |cffff8000(%d --> %d KiB)", t*1000, i, compsize, mem)
420 end
421 tt, tmem = (GetTime() - tt), (gcinfo() - tmem)
422 self:Print("|cff80ff80%d ms|r All sets |cffff8000(%d --> %d KiB)", tt*1000, loadsize, tmem)
423 end
424  
425  
426 --------------------------------
427 -- Load this bitch! --
428 --------------------------------
429 libobj:Register(lib)