vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 --[[
2 Name: RosterLib-2.0
3 Revision: $Revision: 9839 $
4 X-ReleaseDate: "$Date: 2006-08-10 08:55:29 +0200 (Thu, 10 Aug 2006) $
5 Author: Maia (maia.proudmoore@gmail.com)
6 Website: http://wiki.wowace.com/index.php/RosterLib-2.0
7 Documentation: http://wiki.wowace.com/index.php/RosterLib-2.0_API_Documentation
8 SVN: http://svn.wowace.com/root/trunk/RosterLib-2.0/
9 Description: party/raid roster management
10 Dependencies: AceLibrary, AceOO-2.0, AceEvent-2.0
11 ]]
12  
13 local MAJOR_VERSION = "RosterLib-2.0"
14 local MINOR_VERSION = "$Revision: 9839 $"
15  
16 if not AceLibrary then error(vmajor .. " requires AceLibrary.") end
17 if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
18 if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end
19 if not AceLibrary:HasInstance("AceEvent-2.0") then error(MAJOR_VERSION .. " requires AceEvent-2.0") end
20  
21 local updatedUnits = {}
22 local unknownUnits = {}
23 local RosterLib = {}
24 local roster
25  
26 ------------------------------------------------
27 -- activate, enable, disable
28 ------------------------------------------------
29  
30 local function print(text)
31 ChatFrame3:AddMessage(text)
32 end
33  
34 local function activate(self, oldLib, oldDeactivate)
35 RosterLib = self
36 if oldLib then
37 self.roster = oldLib.roster
38 oldLib:UnregisterAllEvents()
39 oldLib:CancelAllScheduledEvents()
40 end
41 if not self.roster then self.roster = {} end
42 if oldDeactivate then oldDeactivate(oldLib) end
43 roster = self.roster
44 end
45  
46  
47 local function external(self, major, instance)
48 if major == "AceEvent-2.0" then
49 AceEvent = instance
50 AceEvent:embed(self)
51 self:UnregisterAllEvents()
52 self:CancelAllScheduledEvents()
53 if AceEvent:IsFullyInitialized() then
54 self:AceEvent_FullyInitialized()
55 else
56 self:RegisterEvent("AceEvent_FullyInitialized", "AceEvent_FullyInitialized", true)
57 end
58 elseif major == "Compost-2.0" then
59 Compost = instance
60 end
61 end
62  
63  
64 function RosterLib:Enable()
65 -- not used anymore, but as addons still might be calling this method, we're keeping it.
66 end
67  
68  
69 function RosterLib:Disable()
70 -- not used anymore, but as addons still might be calling this method, we're keeping it.
71 end
72  
73 ------------------------------------------------
74 -- Internal functions
75 ------------------------------------------------
76  
77 function RosterLib:AceEvent_FullyInitialized()
78 self:TriggerEvent("RosterLib_Enabled")
79 self:RegisterEvent("RAID_ROSTER_UPDATE","ScanFullRoster")
80 self:RegisterEvent("PARTY_MEMBERS_CHANGED","ScanFullRoster")
81 self:RegisterEvent("UNIT_PET","ScanPet")
82 self:ScanFullRoster()
83 end
84  
85  
86 ------------------------------------------------
87 -- Unit iterator
88 ------------------------------------------------
89  
90 local playersent, petsent, unitcount, petcount, pmem, rmem, unit
91  
92 local function NextUnit()
93 -- STEP 1: pet
94 if not petsent then
95 petsent = true
96 if rmem == 0 then
97 unit = "pet"
98 if UnitExists(unit) then return unit end
99 end
100 end
101 -- STEP 2: player
102 if not playersent then
103 playersent = true
104 if rmem == 0 then
105 unit = "player"
106 if UnitExists(unit) then return unit end
107 end
108 end
109 -- STEP 3: raid units
110 if rmem > 0 then
111 -- STEP 3a: pet units
112 for i = petcount, rmem do
113 unit = string.format("raidpet%d", i)
114 petcount = petcount + 1
115 if UnitExists(unit) then return unit end
116 end
117 -- STEP 3b: player units
118 for i = unitcount, rmem do
119 unit = string.format("raid%d", i)
120 unitcount = unitcount + 1
121 if UnitExists(unit) then return unit end
122 end
123 -- STEP 4: party units
124 elseif pmem > 0 then
125 -- STEP 3a: pet units
126 for i = petcount, pmem do
127 unit = string.format("partypet%d", i)
128 petcount = petcount + 1
129 if UnitExists(unit) then return unit end
130 end
131 -- STEP 3b: player units
132 for i = unitcount, pmem do
133 unit = string.format("party%d", i)
134 unitcount = unitcount + 1
135 if UnitExists(unit) then return unit end
136 end
137 end
138 end
139  
140 local function UnitIterator()
141 playersent, petsent, unitcount, petcount, pmem, rmem = false, false, 1, 1, GetNumPartyMembers(), GetNumRaidMembers()
142 return NextUnit
143 end
144  
145 ------------------------------------------------
146 -- Roster code
147 ------------------------------------------------
148  
149  
150 function RosterLib:ScanFullRoster()
151 -- save all units we currently have, this way we can check who to remove from roster later.
152 local temp = Compost and Compost:Acquire() or {}
153 for name in pairs(roster) do
154 temp[name] = true
155 end
156 -- update data
157 for unitid in UnitIterator() do
158 local name = self:CreateOrUpdateUnit(unitid)
159 -- we successfully added a unit, so we don't need to remove it next step
160 if name then temp[name] = nil end
161 end
162 -- clear units we had in roster that either left the raid or are unknown for some reason.
163 for name in pairs(temp) do
164 self:RemoveUnit(name)
165 end
166 if Compost then Compost:Reclaim(temp) end
167 self:ProcessRoster()
168 end
169  
170  
171 function RosterLib:ScanPet(owner)
172 local unitid = self:GetPetFromOwner(owner)
173 if not unitid then
174 return
175 elseif not UnitExists(unitid) then
176 unknownUnits[unitid] = nil
177 -- find the pet in the roster we need to delete
178 for _,u in pairs(roster) do
179 if u.unitid == unitid then
180 self:RemoveUnit(u.name)
181 end
182 end
183 else
184 self:CreateOrUpdateUnit(unitid)
185 end
186 self:ProcessRoster()
187 end
188  
189  
190 function RosterLib:GetPetFromOwner(id)
191 -- convert party3 crap to raid IDs when in raid.
192 local owner = self:GetUnitIDFromUnit(id)
193 if not owner then
194 return
195 end
196 -- get ID
197 if string.find(owner,"raid") then
198 return string.gsub(owner, "raid", "raidpet")
199 elseif string.find(owner,"party") then
200 return string.gsub(owner, "party", "partypet")
201 elseif owner == "player" then
202 return "pet"
203 else
204 return nil
205 end
206 end
207  
208  
209 function RosterLib:ScanUnknownUnits()
210 local name
211 for unitid in pairs(unknownUnits) do
212 if UnitExists(unitid) then
213 name = self:CreateOrUpdateUnit(unitid)
214 else
215 unknownUnits[unitid] = nil
216 end
217 -- some pets never have a name. too bad for them, farewell!
218 if not name and string.find(unitid,"pet") then
219 unknownUnits[unitid] = nil
220 end
221 end
222 self:ProcessRoster()
223 end
224  
225  
226 function RosterLib:ProcessRoster()
227 if next(updatedUnits, nil) then
228 self:TriggerEvent("RosterLib_RosterChanged", updatedUnits)
229 for name in pairs(updatedUnits) do
230 local u = updatedUnits[name]
231 self:TriggerEvent("RosterLib_UnitChanged", u.unitid, u.name, u.class, u.subgroup, u.rank, u.oldname, u.oldunitid, u.oldclass, u.oldsubgroup, u.oldrank)
232 if Compost then Compost:Reclaim(updatedUnits[name]) end
233 updatedUnits[name] = nil
234 end
235 end
236 if next(unknownUnits, nil) then
237 self:CancelScheduledEvent("ScanUnknownUnits")
238 self:ScheduleEvent("ScanUnknownUnits",self.ScanUnknownUnits, 1, self)
239 end
240 end
241  
242  
243 function RosterLib:CreateOrUpdateUnit(unitid)
244 local old = nil
245 -- check for name
246 local name = UnitName(unitid)
247 if name and name ~= UNKNOWNOBJECT and name ~= UKNOWNBEING and not UnitIsCharmed(unitid) then
248 -- clear stuff
249 unknownUnits[unitid] = nil
250 -- return if a pet attempts to replace a player name
251 -- this doesnt fix the problem with 2 pets overwriting each other FIXME
252 if string.find(unitid,"pet") then
253 if roster[name] and roster[name].class ~= "pet" then
254 return name
255 end
256 end
257 -- save old data if existing
258 if roster[name] then
259 old = Compost and Compost:Acquire() or {}
260 old.name = roster[name].name
261 old.unitid = roster[name].unitid
262 old.class = roster[name].class
263 old.rank = roster[name].rank
264 old.subgroup = roster[name].subgroup
265 end
266 -- object
267 if not roster[name] then
268 roster[name] = Compost and Compost:Acquire() or {}
269 end
270 -- name
271 roster[name].name = name
272 -- unitid
273 roster[name].unitid = unitid
274 -- class
275 if string.find(unitid,"pet") then
276 roster[name].class = "PET"
277 else
278 _,roster[name].class = UnitClass(unitid)
279 end
280 -- subgroup and rank
281 if GetNumRaidMembers() > 0 then
282 local _,_,num = string.find(unitid, "(%d+)")
283 _,roster[name].rank,roster[name].subgroup = GetRaidRosterInfo(num)
284 else
285 roster[name].subgroup = 1
286 roster[name].rank = 0
287 end
288 -- compare data
289 if not old
290 or roster[name].name ~= old.name
291 or roster[name].unitid ~= old.unitid
292 or roster[name].class ~= old.class
293 or roster[name].subgroup ~= old.subgroup
294 or roster[name].rank ~= old.rank
295 then
296 updatedUnits[name] = Compost and Compost:Acquire() or {}
297 updatedUnits[name].oldname = (old and old.name) or nil
298 updatedUnits[name].oldunitid = (old and old.unitid) or nil
299 updatedUnits[name].oldclass = (old and old.class) or nil
300 updatedUnits[name].oldsubgroup = (old and old.subgroup) or nil
301 updatedUnits[name].oldrank = (old and old.rank) or nil
302 updatedUnits[name].name = roster[name].name
303 updatedUnits[name].unitid = roster[name].unitid
304 updatedUnits[name].class = roster[name].class
305 updatedUnits[name].subgroup = roster[name].subgroup
306 updatedUnits[name].rank = roster[name].rank
307 end
308 -- compost our table
309 if old and Compost then
310 Compost:Reclaim(old)
311 end
312 return name
313 else
314 unknownUnits[unitid] = true
315 return false
316 end
317 end
318  
319  
320 function RosterLib:RemoveUnit(name)
321 updatedUnits[name] = Compost and Compost:Acquire() or {}
322 updatedUnits[name].oldname = roster[name].name
323 updatedUnits[name].oldunitid = roster[name].unitid
324 updatedUnits[name].oldclass = roster[name].class
325 updatedUnits[name].oldsubgroup = roster[name].subgroup
326 updatedUnits[name].oldrank = roster[name].rank
327 if Compost then Compost:Reclaim(roster[name]) end
328 roster[name] = nil
329 end
330  
331  
332 ------------------------------------------------
333 -- API
334 ------------------------------------------------
335  
336 function RosterLib:GetUnitIDFromName(name)
337 if roster[name] then
338 return roster[name].unitid
339 else
340 return nil
341 end
342 end
343  
344  
345 function RosterLib:GetUnitIDFromUnit(unit)
346 local name = UnitName(unit)
347 if name and roster[name] then
348 return roster[name].unitid
349 else
350 return nil
351 end
352 end
353  
354  
355 function RosterLib:GetUnitObjectFromName(name)
356 if roster[name] then
357 return roster[name]
358 else
359 return nil
360 end
361 end
362  
363  
364 function RosterLib:GetUnitObjectFromUnit(unit)
365 local name = UnitName(unit)
366 if roster[name] then
367 return roster[name]
368 else
369 return nil
370 end
371 end
372  
373  
374 function RosterLib:IterateRoster(pets)
375 local key
376 return function()
377 key = next(roster, key)
378 if key and (pets or roster[key].class ~= "PET") then
379 return roster[key]
380 end
381 end
382 end
383  
384  
385 AceLibrary:Register(RosterLib, MAJOR_VERSION, MINOR_VERSION, activate, nil, external)