Mercurial > wow > ouroloot
comparison core.lua @ 100:a57133ee3c9b
- Allow event callbacks using the standard CallbackHandler scheme. Add
a debug.callback flag with usual semantics.
- Fire an initial set of events. This will take experimentation.
- If restoring g_loot, set metatables on previous entries also.
author | Farmbuyer of US-Kilrogg <farmbuyer@gmail.com> |
---|---|
date | Mon, 30 Jul 2012 19:25:46 +0000 |
parents | 966d06c8d9c9 |
children | f7162a1cadc7 |
comparison
equal
deleted
inserted
replaced
99:966d06c8d9c9 | 100:a57133ee3c9b |
---|---|
203 comm = false, | 203 comm = false, |
204 loot = false, | 204 loot = false, |
205 flow = false, | 205 flow = false, |
206 notraid = false, | 206 notraid = false, |
207 cache = false, | 207 cache = false, |
208 callback = false, | |
208 alsolog = false, | 209 alsolog = false, |
209 } | 210 } |
210 --@debug@ | 211 --@debug@ |
211 DEBUG_PRINT = true | 212 DEBUG_PRINT = true |
212 debug.loot = true | 213 debug.loot = true |
213 debug.comm = true | 214 debug.comm = true |
215 is_guilded = _G.IsInGuild() | |
214 --@end-debug@ | 216 --@end-debug@ |
215 | 217 |
216 -- This looks ugly, but it factors out the load-time decisions from | 218 -- This looks ugly, but it factors out the load-time decisions from |
217 -- the run-time ones. Args to [dp]print are concatenated with spaces. | 219 -- the run-time ones. Args to [dp]print are concatenated with spaces. |
218 if tekdebug then | 220 if tekdebug then |
386 local pprint, tabledump = addon.pprint, flib.tabledump | 388 local pprint, tabledump = addon.pprint, flib.tabledump |
387 local CopyTable = _G.CopyTable | 389 local CopyTable = _G.CopyTable |
388 local GetNumRaidMembers = _G.GetNumGroupMembers or _G.GetNumRaidMembers | 390 local GetNumRaidMembers = _G.GetNumGroupMembers or _G.GetNumRaidMembers |
389 local IsInRaid = _G.IsInRaid or (function() return GetNumRaidMembers() > 0 end) | 391 local IsInRaid = _G.IsInRaid or (function() return GetNumRaidMembers() > 0 end) |
390 -- En masse forward decls of symbols defined inside local blocks | 392 -- En masse forward decls of symbols defined inside local blocks |
391 local _register_bossmod, makedate, create_new_cache, _init, _log | 393 local _register_bossmod, makedate, create_new_cache, _init, _log, _do_loot_metas |
392 local _history_by_loot_id, _setup_unique_replace, _unavoidable_collision | 394 local _history_by_loot_id, _setup_unique_replace, _unavoidable_collision |
393 local _notify_about_change, _notify_about_remote | 395 local _notify_about_change, _notify_about_remote |
394 | 396 |
395 -- Try to extract numbers from the .toc "Version" and munge them into an | 397 -- Try to extract numbers from the .toc "Version" and munge them into an |
396 -- integral form for comparison. The result doesn't need to be meaningful as | 398 -- integral form for comparison. The result doesn't need to be meaningful as |
609 | 611 |
610 -- If unique keys ever change into objects instead of strings, change | 612 -- If unique keys ever change into objects instead of strings, change |
611 -- this into a weakly-keyed table. | 613 -- this into a weakly-keyed table. |
612 mt = { __metatable = 'Should be using setmode.' } | 614 mt = { __metatable = 'Should be using setmode.' } |
613 | 615 |
614 g_uniques = setmetatable (m_reset{}, mt) | 616 g_uniques = _G.setmetatable (m_reset{}, mt) |
615 end | 617 end |
616 | 618 |
617 | 619 |
618 ------ Expiring caches | 620 ------ Expiring caches |
619 --[[ | 621 --[[ |
687 add = _add, | 689 add = _add, |
688 test = _test, | 690 test = _test, |
689 cleanup = cleanup_group:CreateAnimation("Animation"), | 691 cleanup = cleanup_group:CreateAnimation("Animation"), |
690 func = on_alldone, | 692 func = on_alldone, |
691 fifo = {}, | 693 fifo = {}, |
692 hash = setmetatable({}, {__mode='kv'}), | 694 hash = _G.setmetatable({}, {__mode='kv'}), |
693 } | 695 } |
694 c.cleanup:SetOrder(1) | 696 c.cleanup:SetOrder(1) |
695 caches[name] = c | 697 caches[name] = c |
696 return c | 698 return c |
697 end | 699 end |
713 -- VARIABLES_LOADED has fired by this point; test if we're doing something like | 715 -- VARIABLES_LOADED has fired by this point; test if we're doing something like |
714 -- relogging during a raid and already have collected loot data | 716 -- relogging during a raid and already have collected loot data |
715 local OuroLootSV = _G.OuroLootSV | 717 local OuroLootSV = _G.OuroLootSV |
716 g_restore_p = OuroLootSV ~= nil | 718 g_restore_p = OuroLootSV ~= nil |
717 self.dprint('flow', "oninit sets restore as", g_restore_p) | 719 self.dprint('flow', "oninit sets restore as", g_restore_p) |
720 | |
721 -- Primarily for plugins, but can be of use to me also... | |
722 self.callbacks = _G.LibStub("CallbackHandler-1.0"):New(self) | |
723 --function self.callbacks:OnUsed (target_aka_self, eventname) end | |
724 --function self.callbacks:OnUnused (target_aka_self, eventname) end | |
718 | 725 |
719 if _G.OuroLootOptsDB == nil then | 726 if _G.OuroLootOptsDB == nil then |
720 local vclick = self.format_hypertext ([[click here]], ITEM_QUALITY_UNCOMMON, 'help') | 727 local vclick = self.format_hypertext ([[click here]], ITEM_QUALITY_UNCOMMON, 'help') |
721 self:ScheduleTimer(function(s) | 728 self:ScheduleTimer(function(s) |
722 for id in pairs(self.default_itemfilter) do | 729 for id in pairs(self.default_itemfilter) do |
1042 end | 1049 end |
1043 return self:NewModule(modname) | 1050 return self:NewModule(modname) |
1044 end | 1051 end |
1045 end | 1052 end |
1046 | 1053 |
1054 -- We don't want to trigger plugins and another addons as soon as something | |
1055 -- interesting happens, because a nontrivial amount of work happens "quickly" | |
1056 -- after the interesting event: cleanups/fixups, improvs from network, etc. | |
1057 -- So firing a callback is delayed ever so briefly by human standards. | |
1058 -- | |
1059 -- Can't *quite* use the expiring caches for this, but that's okay. | |
1060 do | |
1061 local unpack = _G.unpack | |
1062 local function F (t) | |
1063 addon.callbacks:Fire (unpack(t)) | |
1064 flib.del(t) | |
1065 end | |
1066 function addon:Fire (...) | |
1067 self.dprint('callback', ...) | |
1068 local capture = flib.new(...) | |
1069 self:ScheduleTimer (F, 1.2, capture) | |
1070 end | |
1071 end | |
1072 | |
1047 | 1073 |
1048 ------ Event handlers | 1074 ------ Event handlers |
1049 function addon:_clear_SVs() | 1075 function addon:_clear_SVs() |
1050 g_loot = {} -- not saved, just fooling PLAYER_LOGOUT tests | 1076 g_loot = {} -- not saved, just fooling PLAYER_LOGOUT tests |
1051 _G.OuroLootSV = nil | 1077 _G.OuroLootSV = nil |
1126 if r.online ~= R_LEFT and not UnitInRaid(name) then | 1152 if r.online ~= R_LEFT and not UnitInRaid(name) then |
1127 r.online = R_LEFT | 1153 r.online = R_LEFT |
1128 r.leave = now | 1154 r.leave = now |
1129 end | 1155 end |
1130 end | 1156 end |
1157 | |
1158 -- XXX somewhere in here, we could fire a useful callback event | |
1131 | 1159 |
1132 if redo then | 1160 if redo then |
1133 redo_count = redo_count + 1 | 1161 redo_count = redo_count + 1 |
1134 end | 1162 end |
1135 redo = false | 1163 redo = false |
1605 end | 1633 end |
1606 self:Print "Baron Steamroller has been slain. Congratulations on your rug." | 1634 self:Print "Baron Steamroller has been slain. Congratulations on your rug." |
1607 | 1635 |
1608 elseif cmd == "debug" then | 1636 elseif cmd == "debug" then |
1609 if arg then | 1637 if arg then |
1638 self.is_guilded = _G.IsInGuild() | |
1610 self.debug[arg] = not self.debug[arg] | 1639 self.debug[arg] = not self.debug[arg] |
1611 _G.print(arg,self.debug[arg]) | 1640 _G.print(arg,self.debug[arg]) |
1612 if self.debug[arg] then self.DEBUG_PRINT = true end | 1641 if self.debug[arg] then self.DEBUG_PRINT = true end |
1613 else | 1642 else |
1614 self.DEBUG_PRINT = not self.DEBUG_PRINT | 1643 self.DEBUG_PRINT = not self.DEBUG_PRINT |
1703 self.enabled = not opt_bcast_only | 1732 self.enabled = not opt_bcast_only |
1704 g_seeing_oldsigs = nil | 1733 g_seeing_oldsigs = nil |
1705 if opt_threshold then | 1734 if opt_threshold then |
1706 self:SetThreshold (opt_threshold, --[[quiet_p=]]true) | 1735 self:SetThreshold (opt_threshold, --[[quiet_p=]]true) |
1707 end | 1736 end |
1737 self:Fire ('Activate', self.enabled, self.rebroadcast, self.threshold) | |
1708 self:Print("Now %s; threshold currently %s.", | 1738 self:Print("Now %s; threshold currently %s.", |
1709 self.enabled and "tracking" or "only broadcasting", | 1739 self.enabled and "tracking" or "only broadcasting", |
1710 self.thresholds[self.threshold]) | 1740 self.thresholds[self.threshold]) |
1711 self:broadcast('revcheck',version_large) | 1741 self:broadcast('revcheck',version_large) |
1712 end | 1742 end |
1717 self.enabled = false | 1747 self.enabled = false |
1718 self.rebroadcast = false | 1748 self.rebroadcast = false |
1719 self:UnregisterEvent(RAID_ROSTER_UPDATE_EVENT) | 1749 self:UnregisterEvent(RAID_ROSTER_UPDATE_EVENT) |
1720 self:UnregisterEvent("PLAYER_ENTERING_WORLD") | 1750 self:UnregisterEvent("PLAYER_ENTERING_WORLD") |
1721 self:UnregisterEvent("CHAT_MSG_LOOT") | 1751 self:UnregisterEvent("CHAT_MSG_LOOT") |
1752 self:Fire ('Deactivate') | |
1722 self:Print("Deactivated.") | 1753 self:Print("Deactivated.") |
1723 end | 1754 end |
1724 | 1755 |
1725 function addon:Clear(verbose_p) | 1756 function addon:Clear(verbose_p) |
1726 local repopup, st | 1757 local repopup, st |
1742 else | 1773 else |
1743 self:Print("Current loot data cleared.") | 1774 self:Print("Current loot data cleared.") |
1744 end | 1775 end |
1745 end | 1776 end |
1746 _init(self,st) | 1777 _init(self,st) |
1778 self:Fire ('Reset') | |
1747 if repopup then | 1779 if repopup then |
1748 addon:BuildMainDisplay() | 1780 addon:BuildMainDisplay() |
1749 end | 1781 end |
1750 end | 1782 end |
1751 | 1783 |
1994 self.hist_clean = nil | 2026 self.hist_clean = nil |
1995 if g_restore_p then | 2027 if g_restore_p then |
1996 g_loot = _G.OuroLootSV | 2028 g_loot = _G.OuroLootSV |
1997 self.popped = #g_loot > 0 | 2029 self.popped = #g_loot > 0 |
1998 self.dprint('flow', "restoring", #g_loot, "entries") | 2030 self.dprint('flow', "restoring", #g_loot, "entries") |
2031 _do_loot_metas() | |
1999 self:ScheduleTimer("Activate", 12, opts.threshold) | 2032 self:ScheduleTimer("Activate", 12, opts.threshold) |
2000 -- FIXME printed could be too large if entries were deleted, how much do we care? | 2033 -- FIXME printed could be too large if entries were deleted, how much do we care? |
2001 self.sharder = opts.autoshard | 2034 self.sharder = opts.autoshard |
2002 else | 2035 else |
2003 g_loot = {} | 2036 g_loot = {} |
2078 break | 2111 break |
2079 end | 2112 end |
2080 end | 2113 end |
2081 end | 2114 end |
2082 bossi = addon._addBossEntry(boss) | 2115 bossi = addon._addBossEntry(boss) |
2083 -- addon. | 2116 addon:Fire ('NewBoss', boss) |
2084 bossi = addon._adjustBossOrder (bossi, g_boss_signpost) or bossi | 2117 bossi = addon._adjustBossOrder (bossi, g_boss_signpost) or bossi |
2085 g_boss_signpost = nil | 2118 g_boss_signpost = nil |
2086 addon.latest_instance = boss.instance | 2119 addon.latest_instance = boss.instance |
2087 addon.dprint('loot', "added boss entry", bossi) | 2120 addon.dprint('loot', "added boss entry", bossi) |
2088 if boss.reason == 'kill' then | 2121 if boss.reason == 'kill' then |
2228 | 2261 |
2229 -- Adding entries to the loot record, and tracking the corresponding timestamp. | 2262 -- Adding entries to the loot record, and tracking the corresponding timestamp. |
2230 do | 2263 do |
2231 local rawget, setmetatable = _G.rawget, _G.setmetatable | 2264 local rawget, setmetatable = _G.rawget, _G.setmetatable |
2232 | 2265 |
2233 -- This shouldn't be required. /sadface | 2266 --@debug@ |
2267 local tos = {} | |
2268 tos.time = function (e) | |
2269 return e.startday.text | |
2270 end | |
2271 tos.boss = function (e) | |
2272 return e.bossname .. '/' .. e.reason | |
2273 end | |
2274 tos.loot = function (e) | |
2275 return e.itemname .. '/' .. e.person .. '/' .. e.unique .. '/' | |
2276 .. tostring(e.disposition) .. (e.extratext and ('/'..e.extratext) or '') | |
2277 end | |
2278 --@end-debug@ | |
2234 local loot_entry_mt = { | 2279 local loot_entry_mt = { |
2235 __index = function (e,key) | 2280 __index = function (e,key) |
2281 -- This shouldn't be required, as the refresh should be picking | |
2282 -- it up already. Sigh. | |
2236 if key == 'cols' then | 2283 if key == 'cols' then |
2237 pprint('mt', e.kind, "key is", key) | 2284 pprint('mt', e.kind, "key is", key) |
2238 --tabledump(e) -- not actually that useful | |
2239 addon:_fill_out_eoi_data(1) | 2285 addon:_fill_out_eoi_data(1) |
2240 end | 2286 end |
2241 return rawget(e,key) | 2287 return rawget(e,key) |
2242 end | 2288 end, |
2289 --@debug@ | |
2290 __tostring = function (e) | |
2291 local k = e.kind | |
2292 if k then | |
2293 return ("<%s/%s>"):format(k, tos[k] and tos[k](e) or "?") | |
2294 end | |
2295 return "<unknown loot entry type>" | |
2296 end, | |
2297 --@end-debug@ | |
2243 } | 2298 } |
2299 function _do_loot_metas() | |
2300 for i,e in ipairs(g_loot) do | |
2301 setmetatable(e,loot_entry_mt) | |
2302 end | |
2303 _do_loot_metas = nil | |
2304 end | |
2244 | 2305 |
2245 -- Given a loot index, searches backwards for a timestamp. Returns that | 2306 -- Given a loot index, searches backwards for a timestamp. Returns that |
2246 -- index and the time entry, or nil if it falls off the beginning. Pass an | 2307 -- index and the time entry, or nil if it falls off the beginning. Pass an |
2247 -- optional second index to search no earlier than that. | 2308 -- optional second index to search no earlier than that. |
2248 -- May also be able to make good use of this in forum-generation routine. | 2309 -- May also be able to make good use of this in forum-generation routine. |
2324 e.stamp = time_t --localuptime | 2385 e.stamp = time_t --localuptime |
2325 if e.kind == 'loot' then | 2386 if e.kind == 'loot' then |
2326 if (not e.unique) or (#e.unique==0) then | 2387 if (not e.unique) or (#e.unique==0) then |
2327 e.unique = e.id .. (e.disposition or e.person) .. _G.date("%Y/%m/%d %H:%M",e.stamp) | 2388 e.unique = e.id .. (e.disposition or e.person) .. _G.date("%Y/%m/%d %H:%M",e.stamp) |
2328 end | 2389 end |
2390 addon:Fire ('NewLootEntry', e) | |
2329 end | 2391 end |
2330 local index = #g_loot + 1 | 2392 local index = #g_loot + 1 |
2331 g_loot[index] = e | 2393 g_loot[index] = e |
2394 addon:Fire ('NewEOIEntry', e) | |
2332 return index | 2395 return index |
2333 end | 2396 end |
2334 | 2397 |
2335 -- Safety wrapper only. | 2398 -- Safety/convenience wrapper only. |
2336 -- XXX Maybe pprint something here. | |
2337 function addon._addBossEntry (e) | 2399 function addon._addBossEntry (e) |
2338 local ret = addon._addLootEntry(e) | 2400 local ret = addon._addLootEntry(e) |
2339 assert(e.kind=='boss') | 2401 assert(e.kind=='boss') |
2340 local needSize = e.maxsize == nil | 2402 local needSize = e.maxsize == nil |
2341 local needSnap = e.raidersnap == nil | 2403 local needSnap = e.raidersnap == nil |
2344 local ss, max, inst = addon:snapshot_raid() | 2406 local ss, max, inst = addon:snapshot_raid() |
2345 if needSize then e.maxsize = max end | 2407 if needSize then e.maxsize = max end |
2346 if needSnap then e.raidersnap = ss end | 2408 if needSnap then e.raidersnap = ss end |
2347 if needInst then e.instance = inst end | 2409 if needInst then e.instance = inst end |
2348 end | 2410 end |
2411 addon:Fire ('NewBossEntry', e) | |
2349 return ret | 2412 return ret |
2350 end | 2413 end |
2351 | 2414 |
2352 -- Problem: (1) boss kill happens, (2) fast looting happens, (3) boss | 2415 -- Problem: (1) boss kill happens, (2) fast looting happens, (3) boss |
2353 -- cache cleanup fires. Result: loot shows up before boss kill entry. | 2416 -- cache cleanup fires. Result: loot shows up before boss kill entry. |
2550 local clicky | 2613 local clicky |
2551 function addon:horrible_horrible_error (err_msg) | 2614 function addon:horrible_horrible_error (err_msg) |
2552 if self.display then | 2615 if self.display then |
2553 local d = self.display | 2616 local d = self.display |
2554 if d then | 2617 if d then |
2618 -- Take this down a piece at a time, on the assumption that | |
2619 -- the main window won't be able to do so. | |
2555 local gui = d:GetUserData("GUI state") | 2620 local gui = d:GetUserData("GUI state") |
2556 local eoist = gui.eoiST | 2621 local eoist = gui.eoiST |
2557 if eoist then eoist:Hide() end | 2622 if eoist then eoist:Hide() end |
2558 local histst = gui.histST | 2623 local histst = gui.histST |
2559 if histst then histst:Hide() end | 2624 if histst then histst:Hide() end |
2885 h.when[U] = when | 2950 h.when[U] = when |
2886 h.id[U] = e.id | 2951 h.id[U] = e.id |
2887 h.count[U] = e.count | 2952 h.count[U] = e.count |
2888 | 2953 |
2889 g_uniques[U] = { loot = lootindex, history = e.person } | 2954 g_uniques[U] = { loot = lootindex, history = e.person } |
2955 self:Fire ('NewHistory', e.person, U) | |
2890 end | 2956 end |
2891 | 2957 |
2892 -- Create new history table based on current loot. | 2958 -- Create new history table based on current loot. |
2893 function addon:rewrite_history (realmname) | 2959 function addon:rewrite_history (realmname) |
2894 local r = assert(realmname) | 2960 local r = assert(realmname) |
3102 end | 3168 end |
3103 if self.display then | 3169 if self.display then |
3104 self.display:GetUserData("GUI state").eoiST:OuroLoot_Refresh(index) | 3170 self.display:GetUserData("GUI state").eoiST:OuroLoot_Refresh(index) |
3105 self:redisplay() | 3171 self:redisplay() |
3106 end | 3172 end |
3173 self:Fire ('Reassign', unique, id, e, from_name, to_name) | |
3107 return index | 3174 return index |
3108 end | 3175 end |
3109 | 3176 |
3110 local function expunge (player, index_or_unique) | 3177 local function expunge (player, index_or_unique) |
3111 local i,u | 3178 local i,u |
3126 assert(#u>0) | 3193 assert(#u>0) |
3127 tremove (player.unique, i) | 3194 tremove (player.unique, i) |
3128 player.when[u], player.id[u], player.count[u] = nil, nil, nil | 3195 player.when[u], player.id[u], player.count[u] = nil, nil, nil |
3129 g_uniques[u] = nil | 3196 g_uniques[u] = nil |
3130 addon.hist_clean = nil | 3197 addon.hist_clean = nil |
3198 addon:Fire ('DelHistory', player.name, u) | |
3131 return #player.unique | 3199 return #player.unique |
3132 end | 3200 end |
3133 | 3201 |
3134 -- Mirror of _addHistoryEntry. Arguments are either: | 3202 -- Mirror of _addHistoryEntry. Arguments are either: |
3135 -- E - loot entry | 3203 -- E - loot entry |
3305 -- A unique tag has been set by this point. | 3373 -- A unique tag has been set by this point. |
3306 if how == "local" then | 3374 if how == "local" then |
3307 unique = assert(e.unique) | 3375 unique = assert(e.unique) |
3308 self:vbroadcast('mark', unique, id, olddisp, newdisp) | 3376 self:vbroadcast('mark', unique, id, olddisp, newdisp) |
3309 end | 3377 end |
3378 self:Fire ('MarkAs', unique, id, e, olddisp or 'normal', newdisp or 'normal') | |
3310 return index | 3379 return index |
3311 end | 3380 end |
3312 end | 3381 end |
3313 | 3382 |
3314 | 3383 |
3345 function addon:broadcast(tag,...) | 3414 function addon:broadcast(tag,...) |
3346 local msg = assemble(tag,...) | 3415 local msg = assemble(tag,...) |
3347 self.dprint('comm', "<broadcast>:", msg) | 3416 self.dprint('comm', "<broadcast>:", msg) |
3348 self:SendCommMessage(self.ident, msg, "RAID") | 3417 self:SendCommMessage(self.ident, msg, "RAID") |
3349 -- this is what lets us debug our own message traffic: | 3418 -- this is what lets us debug our own message traffic: |
3350 if self.debug.comm then | 3419 if self.debug.comm and self.is_guilded then |
3351 self:SendCommMessage(self.ident, msg, "GUILD") | 3420 self:SendCommMessage(self.ident, msg, "GUILD") |
3352 end | 3421 end |
3353 end | 3422 end |
3354 -- whispercast(<to>, 'tag', <stuff>) | 3423 -- whispercast(<to>, 'tag', <stuff>) |
3355 function addon:whispercast(to,...) | 3424 function addon:whispercast(to,...) |