Mercurial > wow > ouroloot
changeset 102:fe04f5c4114a
- expiring cache callback arg, handle new entries coming in during the
same loop at the previous ones ALL being removed
TODO: rework other "candidate" caches to use this instead
- raider snapshots use string tokens for 'online' field
- document callback args
- CheckBoxSmallLabel preemptively apply proposed fix for ace3 ticket 304
- now that option toggles are not wedged into tight space, revert to
using standard CheckBox widget instead of small-label variant
(go back if ticket 304 is not fixed for release)
author | Farmbuyer of US-Kilrogg <farmbuyer@gmail.com> |
---|---|
date | Sat, 04 Aug 2012 22:03:05 +0000 |
parents | f7162a1cadc7 |
children | dc8a23a47b03 |
files | AceGUIWidget-CheckBoxSmallLabel.lua core.lua options.lua text_tabs.lua |
diffstat | 4 files changed, 130 insertions(+), 42 deletions(-) [+] |
line wrap: on
line diff
--- a/AceGUIWidget-CheckBoxSmallLabel.lua Wed Aug 01 06:51:52 2012 +0000 +++ b/AceGUIWidget-CheckBoxSmallLabel.lua Sat Aug 04 22:03:05 2012 +0000 @@ -111,6 +111,9 @@ self.frame:Disable() self.text:SetTextColor(0.5, 0.5, 0.5) SetDesaturation(self.check, true) + if self.desc then + self.desc:SetTextColor(0.5, 0.5, 0.5) + end else self.frame:Enable() self.text:SetTextColor(1, 1, 1) @@ -119,6 +122,9 @@ else SetDesaturation(self.check, false) end + if self.desc then + self.desc:SetTextColor(1, 1, 1) + end end end,
--- a/core.lua Wed Aug 01 06:51:52 2012 +0000 +++ b/core.lua Sat Aug 04 22:03:05 2012 +0000 @@ -14,11 +14,11 @@ - sex 1 = unknown/error, 2 = male, 3 = female - level can be 0 if player was offline at the time - guild guild name, or missing if unguilded -- online 1 = online, 2 = offline, 3 = no longer in raid +- online 'online', 'offline', 'no_longer' [no longer in raid group] [both of these next two fields use time_t values:] - join time player joined the raid (or first time we've seen them) - leave time player left the raid (or time we've left the raid, if - 'online' is not 3) + 'online' is not 'no_longer') Common g_loot entry indices: - kind time/boss/loot @@ -77,7 +77,7 @@ ------ Addon member data ------ Globals ------ Expiring caches ------- Ace3 framework stuff +------ Ace3 framework stuff (callback 'events', search for LCALLBACK) ------ Event handlers ------ Slash command handler ------ On/off @@ -101,7 +101,7 @@ OuroLootSV = nil -- possible copy of g_loot OuroLootSV_saved = nil -- table of copies of saved texts, default nil; keys -- are numeric indices of tables, subkeys of those - -- are name/forum/attend/date + -- are name/forum/attend/date OuroLootSV_hist = nil OuroLootSV_log = {} @@ -629,61 +629,72 @@ cache:test(foo) -- returns false cache:test(bar) -- returns true ....5 seconds pass - ....bar also gone, cleanup() called + ....bar also gone, cleanup() called: +function cleanup (expired_entries) + for i = 1, #expired_entries do -- this table is in strict FIFO order + print(i, expired_entries[i]) + -- 1 foo + -- 2 bar + end +end ]] do local caches = {} local cleanup_group = _G.AnimTimerFrame:CreateAnimationGroup() - local time = _G.time + local time, next = _G.time, _G.next + local new, del = flib.new, flib.del cleanup_group:SetLooping("REPEAT") cleanup_group:SetScript("OnLoop", function(cg) addon.dprint('cache',"OnLoop firing") local now = time() - local alldone = true + local actives = 0 + local expired = new() -- this is ass-ugly - for name,c in pairs(caches) do + for name,c in next, caches do local fifo = c.fifo local active = #fifo > 0 + actives = actives + (active and 1 or 0) while (#fifo > 0) and (now > fifo[1].t) do - addon.dprint('cache', name, "cache removing", fifo[1].t, "<", fifo[1].m, ">") - tremove(fifo,1) + local datum = tremove(fifo,1) + addon.dprint('cache', name, "cache removing", datum.t, "<", datum.m, ">") + c.hash[datum.m] = nil + tinsert(expired,datum.m) + del(datum) end if active and #fifo == 0 and c.func then addon.dprint('cache', name, "empty, firing cleanup") - c:func() + c.func(expired) end - alldone = alldone and (#fifo == 0) + wipe(expired) end - if alldone then + del(expired) + if actives == 0 then addon.dprint('cache',"OnLoop FINISHING animation group") cleanup_group:Finish() - _G.collectgarbage() else addon.dprint('cache',"OnLoop done, not yet finished") end end) local function _add (cache, x) - local datum = { t=time()+cache.ttl, m=x } + assert(type(x)~='number') + local datum = new() + datum.m = x + datum.t = time() + cache.ttl cache.hash[x] = datum tinsert (cache.fifo, datum) if not cleanup_group:IsPlaying() then addon.dprint('cache', cache.name, "with entry", datum.t, "<", datum.m, "> STARTING animation group") - cache.cleanup:SetDuration(1) -- hmmm cleanup_group:Play() end end local function _test (cache, x) - -- FIXME This can return false positives, if called after the onloop - -- fifo has been removed but before the GC has removed the weak entry. - -- What to do, what to do... try forcing a GC during alldone. return cache.hash[x] ~= nil end function create_new_cache (name, ttl, on_alldone) -- setting OnFinished for cleanup fires at the end of each inner loop, -- with no 'requested' argument to distinguish cases. thus, on_alldone. - -- FWIW, on_alldone is passed this table as its sole argument: local c = { ttl = ttl, name = name, @@ -691,10 +702,13 @@ test = _test, cleanup = cleanup_group:CreateAnimation("Animation"), func = on_alldone, + -- Testing merging these two (_add's 'x' must not be numeric) fifo = {}, - hash = _G.setmetatable({}, {__mode='kv'}), + --hash = {}, } - c.cleanup:SetOrder(1) + c.hash = c.fifo + c.cleanup:SetOrder(1) -- [1,100] range within parent animation + c.cleanup:SetDuration(0.8) -- hmmm caches[name] = c return c end @@ -1052,34 +1066,91 @@ 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. +--[[ LCALLBACK +Standard ace3-style callback registration and dispatching. All player names +are simple (uncolored) strings. The "uniqueID" always refers to the unique +tag string stored as 'unique' in loot entries and used as keys in history. +Item IDs are always of numeric type. + +'Activate', enabled_p, rebroadcast_p, threshold + The two boolean predicates are self-explanatory. The threshold is an + ITEM_QUALITY_* constant integer. + +'Deactivate' + After all system events have been unregistered. + +'Reset' + Clicking "Clear Loot", after all data manipulation is finished. + +'NewBoss', boss + Boss event triggered by a local bossmod (DBM, etc) or a remote OL tracker. + Argument is a g_loot table entry of kind=='boss'. + +'NewBossEntry', boss + New row in primary EOI table of kind=='boss'. Includes all 'NewBoss' + occasions, plus manual boss additions, testing, etc. Arg same as NewBoss. + +'NewLootEntry', loot +'DelLootEntry', loot + New or removed row in primary EOI table of kind=='loot'. Argument is a + g_loot table entry of kind=='loot'. + +'NewEOIEntry', entry +'DelEOIEntry', entry + New or removed row in primary EOI table, of any kind. Argument is the + g_loot entry, already inserted into or removed from g_loot. + +'NewHistory', player_name, uniqueID +'DelHistory', player_name, uniqueID + New or removed entry in player history. Name argument self-explanatory. + ID is the corresponding loot, already inserted into or removed from the + history structures. + +'Reassign', uniqueID, itemID, loot, from_player_name, to_player_name + Loot reassigned from one player to another. Loot represented by the + unique & item IDs, and the g_loot entry of kind=='loot'. The player + names are self-explanatory. + +'MarkAs', uniqueID, itemID, loot, old_disposition, new_disposition + The "Mark as <x>" action (as if from the item right-click menu, possibly + from a remote tracker) has finished. ID & loot arguments are as in + 'Reassign'. The old/new dispositions are those of the g_loot index + "disposition" (described at the top of core.lua), with the added possible + value of "normal" meaning exactly that. +]] do - local mtnewindex = function() error("This table is read-only", 3) end + -- We don't want to trigger plugins or other addons as soon as something + -- interesting happens, because a nontrivial amount of work happens "soon" + -- after the interesting event: cleanups/fixups, improvs from network, + -- etc. So firing a callback is delayed ever so briefly by human scales. + -- + -- For data safety, we replace any table arguments with read-only proxies + -- before passing them to the callbacks. The goal is to prevent accidents, + -- not fraud. + local unpack, setmetatable = _G.unpack, _G.setmetatable + local mtnewindex = function() --[[local]]error("This table is read-only", 3) end local function make_readonly (t) - return _G.setmetatable({}, { + return setmetatable({}, { __newindex = mtnewindex, __index = t, __metatable = false, + __tostring = getmetatable(t) and getmetatable(t).__tostring, }) end - local unpack = _G.unpack - local function F (t) - addon.callbacks:Fire (unpack(t)) - flib.del(t) - end + local queue = create_new_cache ('callbacks', 1.2, function (allcbs) + for _,c in ipairs(allcbs) do + addon.callbacks:Fire (unpack(c)) + flib.del(c) + end + end) function addon:Fire (...) self.dprint('callback', ...) local capture = flib.new(...) for k,v in ipairs(capture) do if type(v) == 'table' then capture[k] = make_readonly(v) end end - self:ScheduleTimer (F, 1.2, capture) + queue:add(capture) end end @@ -1139,7 +1210,7 @@ IsInInstance, UnitIsConnected, UnitClass, UnitRace, UnitSex, UnitLevel, UnitInRaid, UnitIsVisible, GetGuildInfo, GetRaidRosterInfo local time, difftime = time, difftime - local R_ACTIVE, R_OFFLINE, R_LEFT = 1, 2, 3 + local R_ACTIVE, R_OFFLINE, R_LEFT = 'online', 'offline', 'no_longer' local lastevent, now = 0, 0 local redo_count = 0 @@ -2140,6 +2211,8 @@ end wipe(candidates) end + -- Ten seconds is a long time, but occasionally DBM takes for-EVAH to + -- decide that a fight is over. local recent_boss = create_new_cache ('boss', 10, fixup_durations) -- Similar to _do_loot, but duration+ parms only present when locally generated.
--- a/options.lua Wed Aug 01 06:51:52 2012 +0000 +++ b/options.lua Sat Aug 04 22:03:05 2012 +0000 @@ -69,7 +69,7 @@ local error, assert = addon.error, addon.assert local function mktoggle (opt, label, width, desc, opt_func) - local w = mkbutton("CheckBoxSmallLabel", nil, "", desc) + local w = mkbutton("CheckBox", nil, "", desc) w:SetRelativeWidth(width) w:SetType("checkbox") w:SetLabel(label) @@ -510,7 +510,7 @@ grp:SetRelativeWidth(0.60) grp:SetTitle("Output of debugging messages") - w = AceGUI:Create("CheckBoxSmallLabel") + w = AceGUI:Create("CheckBox") w:SetFullWidth(true) w:SetType("checkbox") w:SetLabel("master toggle") @@ -521,7 +521,7 @@ end) grp:AddChild(w) for d,v in pairs(addon.debug) do - w = AceGUI:Create("CheckBoxSmallLabel") + w = AceGUI:Create("CheckBox") w:SetFullWidth(true) w:SetType("checkbox") w:SetLabel(d) @@ -549,7 +549,7 @@ local simple = AceGUI:Create("SimpleGroup") simple:SetLayout("List") simple:SetRelativeWidth(0.35) - w = AceGUI:Create("CheckBoxSmallLabel") + w = AceGUI:Create("CheckBox") --w:SetRelativeWidth(0.35) w:SetFullWidth(true) w:SetType("checkbox") @@ -620,7 +620,7 @@ addon:Print("Can do nothing; DBM testing mod wasn't loaded.") end end) - w:SetDisabled(addon.bossmod_registered ~= 'DBM') + w:SetDisabled(addon.bossmod_registered ~= 'DBM') -- set by :Activate container:AddChild(w) w = mkbutton("GC", [[full GC cycle]]) @@ -824,13 +824,15 @@ --[[ PLUGIN is the module table itself. (This does not actually have to be a plugin created with :[Constrained]NewModule, as long as it has a - GetName method and other parameters here are used appropriately.) + GetName method and + - TEXT is passed + - if OPTIONS is a table, then OPTIONS.args.name exists PARENT is nil to register in the tree list directly. TEXT is either the text to display in the tree list, or nil to use the moduleName field out of PLUGIN (not :GetName()). OPTIONS is either - I) a function to call directly - II) an aceconfig-style options table + I) an aceconfig-style options table + II) a function to call directly (I) Will augment options.args.name with coloring/sizing, if it exists. (Set options.args.name.name before registering.) Will create it if not @@ -851,7 +853,9 @@ text = text or plugin.moduleName local handler - local pdb = self.db:GetNamespace (plugin.moduleName, --[[silent=]]true) + local pdb = plugin.moduleName and + self.db:GetNamespace (plugin.moduleName, --[[silent=]]true) + if type(options) == 'table' then -- AceConfig-style options table aceconfig_list[code] = true
--- a/text_tabs.lua Wed Aug 01 06:51:52 2012 +0000 +++ b/text_tabs.lua Sat Aug 04 22:03:05 2012 +0000 @@ -148,7 +148,7 @@ -- Assumption: everybody is packed into the first N groups. if raidertable then for name,info in pairs(raidertable) do - if info.online ~= 3 then -- 3 == left the raid + if info.online ~= 'no_longer' then -- 'no_longer' == left the raid if (info.subgroup or (NUM_RAID_GROUPS+1)) <= max_group_number then tins (ingroups, name) else