diff 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
line wrap: on
line diff
--- a/core.lua	Sun Jul 29 23:12:18 2012 +0000
+++ b/core.lua	Mon Jul 30 19:25:46 2012 +0000
@@ -205,12 +205,14 @@
 		flow		= false,
 		notraid		= false,
 		cache		= false,
+		callback	= false,
 		alsolog		= false,
 	}
 	--@debug@
 	DEBUG_PRINT		= true
 	debug.loot		= true
 	debug.comm		= true
+	is_guilded		= _G.IsInGuild()
 	--@end-debug@
 
 	-- This looks ugly, but it factors out the load-time decisions from
@@ -388,7 +390,7 @@
 local GetNumRaidMembers = _G.GetNumGroupMembers or _G.GetNumRaidMembers
 local IsInRaid = _G.IsInRaid or (function() return GetNumRaidMembers() > 0 end)
 -- En masse forward decls of symbols defined inside local blocks
-local _register_bossmod, makedate, create_new_cache, _init, _log
+local _register_bossmod, makedate, create_new_cache, _init, _log, _do_loot_metas
 local _history_by_loot_id, _setup_unique_replace, _unavoidable_collision
 local _notify_about_change, _notify_about_remote
 
@@ -611,7 +613,7 @@
 	-- this into a weakly-keyed table.
 	mt = { __metatable = 'Should be using setmode.' }
 
-	g_uniques = setmetatable (m_reset{}, mt)
+	g_uniques = _G.setmetatable (m_reset{}, mt)
 end
 
 
@@ -689,7 +691,7 @@
 			cleanup = cleanup_group:CreateAnimation("Animation"),
 			func = on_alldone,
 			fifo = {},
-			hash = setmetatable({}, {__mode='kv'}),
+			hash = _G.setmetatable({}, {__mode='kv'}),
 		}
 		c.cleanup:SetOrder(1)
 		caches[name] = c
@@ -716,6 +718,11 @@
 	g_restore_p = OuroLootSV ~= nil
 	self.dprint('flow', "oninit sets restore as", g_restore_p)
 
+	-- Primarily for plugins, but can be of use to me also...
+	self.callbacks = _G.LibStub("CallbackHandler-1.0"):New(self)
+	--function self.callbacks:OnUsed (target_aka_self, eventname)  end
+	--function self.callbacks:OnUnused (target_aka_self, eventname)  end
+
 	if _G.OuroLootOptsDB == nil then
 		local vclick = self.format_hypertext ([[click here]], ITEM_QUALITY_UNCOMMON, 'help')
 		self:ScheduleTimer(function(s)
@@ -1044,6 +1051,25 @@
 	end
 end
 
+-- We don't want to trigger plugins and another addons as soon as something
+-- interesting happens, because a nontrivial amount of work happens "quickly"
+-- after the interesting event:  cleanups/fixups, improvs from network, etc.
+-- So firing a callback is delayed ever so briefly by human standards.
+--
+-- Can't *quite* use the expiring caches for this, but that's okay.
+do
+	local unpack = _G.unpack
+	local function F (t)
+		addon.callbacks:Fire (unpack(t))
+		flib.del(t)
+	end
+	function addon:Fire (...)
+		self.dprint('callback', ...)
+		local capture = flib.new(...)
+		self:ScheduleTimer (F, 1.2, capture)
+	end
+end
+
 
 ------ Event handlers
 function addon:_clear_SVs()
@@ -1129,6 +1155,8 @@
 			end
 		end
 
+		-- XXX somewhere in here, we could fire a useful callback event
+
 		if redo then
 			redo_count = redo_count + 1
 		end
@@ -1607,6 +1635,7 @@
 
 		elseif cmd == "debug" then
 			if arg then
+				self.is_guilded = _G.IsInGuild()
 				self.debug[arg] = not self.debug[arg]
 				_G.print(arg,self.debug[arg])
 				if self.debug[arg] then self.DEBUG_PRINT = true end
@@ -1705,6 +1734,7 @@
 	if opt_threshold then
 		self:SetThreshold (opt_threshold, --[[quiet_p=]]true)
 	end
+	self:Fire ('Activate', self.enabled, self.rebroadcast, self.threshold)
 	self:Print("Now %s; threshold currently %s.",
 		self.enabled and "tracking" or "only broadcasting",
 		self.thresholds[self.threshold])
@@ -1719,6 +1749,7 @@
 	self:UnregisterEvent(RAID_ROSTER_UPDATE_EVENT)
 	self:UnregisterEvent("PLAYER_ENTERING_WORLD")
 	self:UnregisterEvent("CHAT_MSG_LOOT")
+	self:Fire ('Deactivate')
 	self:Print("Deactivated.")
 end
 
@@ -1744,6 +1775,7 @@
 		end
 	end
 	_init(self,st)
+	self:Fire ('Reset')
 	if repopup then
 		addon:BuildMainDisplay()
 	end
@@ -1996,6 +2028,7 @@
 		g_loot = _G.OuroLootSV
 		self.popped = #g_loot > 0
 		self.dprint('flow', "restoring", #g_loot, "entries")
+		_do_loot_metas()
 		self:ScheduleTimer("Activate", 12, opts.threshold)
 		-- FIXME printed could be too large if entries were deleted, how much do we care?
 		self.sharder = opts.autoshard
@@ -2080,7 +2113,7 @@
 			end
 		end
 		bossi = addon._addBossEntry(boss)
-		-- addon.
+		addon:Fire ('NewBoss', boss)
 		bossi = addon._adjustBossOrder (bossi, g_boss_signpost) or bossi
 		g_boss_signpost = nil
 		addon.latest_instance = boss.instance
@@ -2230,17 +2263,45 @@
 do
 	local rawget, setmetatable = _G.rawget, _G.setmetatable
 
-	-- This shouldn't be required.  /sadface
+	--@debug@
+	local tos = {}
+	tos.time = function (e)
+		return e.startday.text
+	end
+	tos.boss = function (e)
+		return e.bossname .. '/' .. e.reason
+	end
+	tos.loot = function (e)
+		return e.itemname .. '/' .. e.person .. '/' .. e.unique .. '/'
+			.. tostring(e.disposition) .. (e.extratext and ('/'..e.extratext) or '')
+	end
+	--@end-debug@
 	local loot_entry_mt = {
 		__index = function (e,key)
+			-- This shouldn't be required, as the refresh should be picking
+			-- it up already.  Sigh.
 			if key == 'cols' then
 				pprint('mt', e.kind, "key is", key)
-				--tabledump(e)  -- not actually that useful
 				addon:_fill_out_eoi_data(1)
 			end
 			return rawget(e,key)
+		end,
+		--@debug@
+		__tostring = function (e)
+			local k = e.kind
+			if k then
+				return ("<%s/%s>"):format(k, tos[k] and tos[k](e) or "?")
+			end
+			return "<unknown loot entry type>"
+		end,
+		--@end-debug@
+	}
+	function _do_loot_metas()
+		for i,e in ipairs(g_loot) do
+			setmetatable(e,loot_entry_mt)
 		end
-	}
+		_do_loot_metas = nil
+	end
 
 	-- Given a loot index, searches backwards for a timestamp.  Returns that
 	-- index and the time entry, or nil if it falls off the beginning.  Pass an
@@ -2326,14 +2387,15 @@
 			if (not e.unique) or (#e.unique==0) then
 				e.unique = e.id .. (e.disposition or e.person) .. _G.date("%Y/%m/%d %H:%M",e.stamp)
 			end
+			addon:Fire ('NewLootEntry', e)
 		end
 		local index = #g_loot + 1
 		g_loot[index] = e
+		addon:Fire ('NewEOIEntry', e)
 		return index
 	end
 
-	-- Safety wrapper only.
-	-- XXX Maybe pprint something here.
+	-- Safety/convenience wrapper only.
 	function addon._addBossEntry (e)
 		local ret = addon._addLootEntry(e)
 		assert(e.kind=='boss')
@@ -2346,6 +2408,7 @@
 			if needSnap then e.raidersnap = ss end
 			if needInst then e.instance = inst end
 		end
+		addon:Fire ('NewBossEntry', e)
 		return ret
 	end
 
@@ -2552,6 +2615,8 @@
 		if self.display then
 			local d = self.display
 			if d then
+				-- Take this down a piece at a time, on the assumption that
+				-- the main window won't be able to do so.
 				local gui = d:GetUserData("GUI state")
 				local eoist = gui.eoiST
 				if eoist then eoist:Hide() end
@@ -2887,6 +2952,7 @@
 		h.count[U] = e.count
 
 		g_uniques[U] = { loot = lootindex, history = e.person }
+		self:Fire ('NewHistory', e.person, U)
 	end
 
 	-- Create new history table based on current loot.
@@ -3104,6 +3170,7 @@
 			self.display:GetUserData("GUI state").eoiST:OuroLoot_Refresh(index)
 			self:redisplay()
 		end
+		self:Fire ('Reassign', unique, id, e, from_name, to_name)
 		return index
 	end
 
@@ -3128,6 +3195,7 @@
 		player.when[u], player.id[u], player.count[u] = nil, nil, nil
 		g_uniques[u] = nil
 		addon.hist_clean = nil
+		addon:Fire ('DelHistory', player.name, u)
 		return #player.unique
 	end
 
@@ -3307,6 +3375,7 @@
 			unique = assert(e.unique)
 			self:vbroadcast('mark', unique, id, olddisp, newdisp)
 		end
+		self:Fire ('MarkAs', unique, id, e, olddisp or 'normal', newdisp or 'normal')
 		return index
 	end
 end
@@ -3347,7 +3416,7 @@
 		self.dprint('comm', "<broadcast>:", msg)
 		self:SendCommMessage(self.ident, msg, "RAID")
 		-- this is what lets us debug our own message traffic:
-		if self.debug.comm then
+		if self.debug.comm and self.is_guilded then
 			self:SendCommMessage(self.ident, msg, "GUILD")
 		end
 	end