Dejunk (Sell & Destroy Junk)

Dejunk (Sell & Destroy Junk)

1M Downloads

Request: Add a public API to check if a bag item is junk

plusmouse opened this issue ยท 8 comments

commented

As most of the APIs are private adding a junk detection feature that uses this addon isn't possible, this is a possible API that would let another addon check if an item is junk:

local AddonName, Addon = ...
local Items = Addon:GetModule("Items")
local JunkFilter = Addon:GetModule("JunkFilter")

function Dejunk_IsJunk(bagID, slotID)
  local item = Items:GetItem(bagID, slotID)
  if not item then
    return false
  end
  local isJunk, reason = JunkFilter:IsJunkItem(item)
  return isJunk
end

local E = Addon:GetModule("Events")
local EventManager = Addon:GetModule("EventManager")

function Dejunk_AddJunkUpdatedCallback(callback)
  local wrapper = function() pcall(callback) end
  EventManager:On(E.ListItemAdded, wrapper)
  -- The remaining events don't fire in the Dejunk code, but if they did they'd be used here:
  EventManager:On(E.MainUIClosed, wrapper)
  EventManager:On(E.ListItemRemoved, wrapper)
  EventManager:On(E.ListRemovedAll, wrapper)
end

The code using the API would look like this for Baganator (the addon I work on), so that the junk coin icon and sorting only applies to junk items as set by a user:

Baganator.Utilities.OnAddonLoaded("Dejunk", function()
  if not Dejunk_IsJunk then
    return
  end

  Baganator.API.RegisterJunkPlugin(BAGANATOR_L_DEJUNK, "dejunk", function(bagID, slotID, itemID, itemLink)
    return Dejunk_IsJunk(bagID, slotID)
  end)

  if not Dejunk_AddJunkUpdatedCallback then
    return
  end

  Dejunk_AddJunkUpdatedCallback(function()
    Baganator.API.RequestItemButtonsRefresh()
  end)
end)

(the file this would go in is https://github.com/plusmouse/Baganator/blob/dejunk/API/Plugins.lua#L34-L50 )

Avoiding a public API

There is another possibility that would wouldn't require a public API, adding this snippet somewhere in the codebase:

local AddonName, Addon = ...
local Items = Addon:GetModule("Items")
local JunkFilter = Addon:GetModule("JunkFilter")

EventUtil.ContinueOnAddOnLoaded("Baganator", function()
  Baganator.API.RegisterJunkPlugin("Dejunk", "dejunk", function(bagID, slotID, itemID, itemLink)
    local item = Items:GetItem(bagID, slotID)
    if not item then
      return false
    end
    local isJunk, reason = JunkFilter:IsJunkItem(item)
    return isJunk
  end)
end)
commented

I'm late responding to this, but I think it's a pretty cool idea. I'm leaning towards a public API, but let me think about it some more.

commented

I'll be adding a public API in the next update:

Dejunk/DejunkApi.lua

Lines 21 to 50 in edbcd6f

-- ============================================================================
-- Dejunk API
-- ============================================================================
DejunkApi = {}
--- Adds a listener to be called whenever Dejunk's state changes.
--- The returned function can be called to remove the listener.
--- @param listener fun() The listener to add
--- @return fun(): fun() | nil removeListener Returns the listener if removed; otherwise `nil`.
function DejunkApi:AddListener(listener)
listeners[#listeners + 1] = listener
return function()
for i = #listeners, 1, -1 do
if listeners[i] == listener then
return table.remove(listeners, i)
end
end
end
end
--- Returns `true` if the item in the given bag and slot is junk.
--- @param bagId integer
--- @param slotId integer
--- @return boolean isJunk
function DejunkApi:IsJunk(bagId, slotId)
if StateManager:GetStore() == nil then return false end
local item = Items:GetFreshItem(bagId, slotId)
return item and JunkFilter:IsJunkItem(item) or false
end

Tested with Baganator and it works:

Baganator.Utilities.OnAddonLoaded("Dejunk", function()
  Baganator.API.RegisterJunkPlugin("Dejunk", "dejunk", function(bagID, slotID, itemID, itemLink)
    return DejunkApi:IsJunk(bagID, slotID)
  end)
  DejunkApi:AddListener(Baganator.API.RequestItemButtonsRefresh)
end)
commented

I'm being a slowpoke, but I do still want to add this.

commented

Good to know. Thanks for the update.

commented

Awesome. Thankyou ๐Ÿ˜„

The support for Dejunk is in the latest alpha with it being automatically enabled should Dejunk be enabled. It will make its way into the next regular release in the next 6-24 hours.

commented

@plusmouse I noticed that you're adding a hack to avoid refreshing icons when Dejunk updates its bag cache. So, it seems preferable for me to update the API to allow responding to particular events. For example:

DejunkApi.ListenerEvents = {
  BagsUpdated = E.BagsUpdated,
  StateUpdated = E.StateUpdated
}

local function notifyListeners(event)
  for _, listener in ipairs(listeners) do
    listener(event)
  end
end

EventManager:Once(E.StoreCreated, function()
  EventManager:On(E.BagsUpdated, function() notifyListeners(DejunkApi.ListenerEvents.BagsUpdated) end)
  EventManager:On(E.StateUpdated, function() notifyListeners(DejunkApi.ListenerEvents.StateUpdated) end)
end)

Then, for Baganator, the API could be used like this:

DejunkApi:AddListener(function(event)
  if event ~= DejunkApi.ListenerEvents.BagsUpdated then
    Baganator.API.RequestItemButtonsRefresh()
  end
end)

Since this doesn't break the API, I will probably add something like this in the next update.

commented

That is preferable for me too. I'll update the Baganator code once your API updates release.

Updating all the icons when it doesn't need to costs about 29ms for Baganator's UI on my machine, compared to 7-10ms when doing only the bag icons that need updating.

commented

I've updated Baganator to use the new event arguments