initial commit
This commit is contained in:
620
LibTSM/Service/AuctionScanClasses/ScanManager.lua
Normal file
620
LibTSM/Service/AuctionScanClasses/ScanManager.lua
Normal file
@@ -0,0 +1,620 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- TradeSkillMaster --
|
||||
-- https://tradeskillmaster.com --
|
||||
-- All Rights Reserved - Detailed license information included with addon. --
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
|
||||
-- This file contains code for scanning the auction house
|
||||
local _, TSM = ...
|
||||
local ScanManager = TSM.Init("Service.AuctionScanClasses.ScanManager")
|
||||
local L = TSM.Include("Locale").GetTable()
|
||||
local TempTable = TSM.Include("Util.TempTable")
|
||||
local Log = TSM.Include("Util.Log")
|
||||
local ItemString = TSM.Include("Util.ItemString")
|
||||
local Math = TSM.Include("Util.Math")
|
||||
local ObjectPool = TSM.Include("Util.ObjectPool")
|
||||
local AuctionHouseWrapper = TSM.Include("Service.AuctionHouseWrapper")
|
||||
local Threading = TSM.Include("Service.Threading")
|
||||
local ItemInfo = TSM.Include("Service.ItemInfo")
|
||||
local Query = TSM.Include("Service.AuctionScanClasses.Query")
|
||||
local QueryUtil = TSM.Include("Service.AuctionScanClasses.QueryUtil")
|
||||
local AuctionScanManager = TSM.Include("LibTSMClass").DefineClass("AuctionScanManager")
|
||||
local private = {
|
||||
objectPool = ObjectPool.New("AUCTION_SCAN_MANAGER", AuctionScanManager),
|
||||
}
|
||||
-- arbitrary estimate that finishing the browse request is worth 10% of the query's progress
|
||||
local BROWSE_PROGRESS = 0.1
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- Module Functions
|
||||
-- ============================================================================
|
||||
|
||||
function ScanManager.Get()
|
||||
return private.objectPool:Get()
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- Class Meta Methods
|
||||
-- ============================================================================
|
||||
|
||||
function AuctionScanManager.__init(self)
|
||||
self._resolveSellers = nil
|
||||
self._ignoreItemLevel = nil
|
||||
self._queries = {}
|
||||
self._queriesScanned = 0
|
||||
self._queryDidBrowse = false
|
||||
self._onProgressUpdateHandler = nil
|
||||
self._onQueryDoneHandler = nil
|
||||
self._resultsUpdateCallbacks = {}
|
||||
self._nextSearchItemFunction = nil
|
||||
self._currentSearchChangedCallback = nil
|
||||
self._findResult = {}
|
||||
self._cancelled = false
|
||||
self._shouldPause = false
|
||||
self._paused = false
|
||||
self._scanQuery = nil
|
||||
self._findQuery = nil
|
||||
self._numItems = nil
|
||||
self._queryCallback = function(query, searchRow)
|
||||
for func in pairs(self._resultsUpdateCallbacks) do
|
||||
func(self, query, searchRow)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AuctionScanManager._Release(self)
|
||||
self._resolveSellers = nil
|
||||
self._ignoreItemLevel = nil
|
||||
for _, query in ipairs(self._queries) do
|
||||
query:Release()
|
||||
end
|
||||
wipe(self._queries)
|
||||
self._queriesScanned = 0
|
||||
self._queryDidBrowse = false
|
||||
self._onProgressUpdateHandler = nil
|
||||
self._onQueryDoneHandler = nil
|
||||
wipe(self._resultsUpdateCallbacks)
|
||||
self._nextSearchItemFunction = nil
|
||||
self._currentSearchChangedCallback = nil
|
||||
self._cancelled = false
|
||||
self._shouldPause = false
|
||||
self._paused = false
|
||||
wipe(self._findResult)
|
||||
self._scanQuery = nil
|
||||
if self._findQuery then
|
||||
self._findQuery:Release()
|
||||
self._findQuery = nil
|
||||
end
|
||||
self._numItems = nil
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- Public Class Methods
|
||||
-- ============================================================================
|
||||
|
||||
function AuctionScanManager.Release(self)
|
||||
self:_Release()
|
||||
private.objectPool:Recycle(self)
|
||||
end
|
||||
|
||||
function AuctionScanManager.SetResolveSellers(self, resolveSellers)
|
||||
self._resolveSellers = resolveSellers
|
||||
return self
|
||||
end
|
||||
|
||||
function AuctionScanManager.SetIgnoreItemLevel(self, ignoreItemLevel)
|
||||
self._ignoreItemLevel = ignoreItemLevel
|
||||
return self
|
||||
end
|
||||
|
||||
function AuctionScanManager.SetScript(self, script, handler)
|
||||
if script == "OnProgressUpdate" then
|
||||
self._onProgressUpdateHandler = handler
|
||||
elseif script == "OnQueryDone" then
|
||||
self._onQueryDoneHandler = handler
|
||||
elseif script == "OnCurrentSearchChanged" then
|
||||
self._currentSearchChangedCallback = handler
|
||||
else
|
||||
error("Unknown AuctionScanManager script: "..tostring(script))
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
function AuctionScanManager.AddResultsUpdateCallback(self, func)
|
||||
self._resultsUpdateCallbacks[func] = true
|
||||
end
|
||||
|
||||
function AuctionScanManager.RemoveResultsUpdateCallback(self, func)
|
||||
self._resultsUpdateCallbacks[func] = nil
|
||||
end
|
||||
|
||||
function AuctionScanManager.SetNextSearchItemFunction(self, func)
|
||||
self._nextSearchItemFunction = func
|
||||
end
|
||||
|
||||
function AuctionScanManager.GetNumQueries(self)
|
||||
return #self._queries
|
||||
end
|
||||
|
||||
function AuctionScanManager.QueryIterator(self, offset)
|
||||
return private.QueryIteratorHelper, self._queries, offset or 0
|
||||
end
|
||||
|
||||
function AuctionScanManager.NewQuery(self)
|
||||
local query = Query.Get()
|
||||
self:_AddQuery(query)
|
||||
return query
|
||||
end
|
||||
|
||||
function AuctionScanManager.AddItemListQueriesThreaded(self, itemList)
|
||||
assert(Threading.IsThreadContext())
|
||||
-- remove duplicates
|
||||
local usedItems = TempTable.Acquire()
|
||||
for i = #itemList, 1, -1 do
|
||||
local itemString = itemList[i]
|
||||
if usedItems[itemString] then
|
||||
tremove(itemList, i)
|
||||
end
|
||||
usedItems[itemString] = true
|
||||
end
|
||||
TempTable.Release(usedItems)
|
||||
self._numItems = #itemList
|
||||
QueryUtil.GenerateThreaded(itemList, private.NewQueryCallback, self)
|
||||
end
|
||||
|
||||
function AuctionScanManager.ScanQueriesThreaded(self)
|
||||
assert(Threading.IsThreadContext())
|
||||
self._queriesScanned = 0
|
||||
self._cancelled = false
|
||||
AuctionHouseWrapper.GetAndResetTotalHookedTime()
|
||||
self:_NotifyProgressUpdate()
|
||||
|
||||
-- loop through each filter to perform
|
||||
local allSuccess = true
|
||||
while self._queriesScanned < #self._queries do
|
||||
local query = self._queries[self._queriesScanned + 1]
|
||||
-- run the browse query
|
||||
local querySuccess, numNewResults = self:_ProcessQuery(query)
|
||||
if not querySuccess then
|
||||
allSuccess = false
|
||||
break
|
||||
end
|
||||
self._queriesScanned = self._queriesScanned + 1
|
||||
self:_NotifyProgressUpdate()
|
||||
if self._onQueryDoneHandler then
|
||||
self:_onQueryDoneHandler(query, numNewResults)
|
||||
end
|
||||
self:_Pause()
|
||||
end
|
||||
|
||||
if allSuccess then
|
||||
local hookedTime, topAddon, topTime = AuctionHouseWrapper.GetAndResetTotalHookedTime()
|
||||
if hookedTime > 1 and topAddon ~= "Blizzard_AuctionHouseUI" then
|
||||
Log.PrintfUser(L["Scan was slowed down by %s seconds by other AH addons (%s seconds by %s)."], Math.Round(hookedTime, 0.1), Math.Round(topTime, 0.1), topAddon)
|
||||
end
|
||||
end
|
||||
return allSuccess
|
||||
end
|
||||
|
||||
function AuctionScanManager.FindAuctionThreaded(self, findSubRow, noSeller)
|
||||
assert(Threading.IsThreadContext())
|
||||
wipe(self._findResult)
|
||||
if TSM.IsWowClassic() then
|
||||
return self:_FindAuctionThreaded(findSubRow, noSeller)
|
||||
else
|
||||
return self:_FindAuctionThreaded83(findSubRow, noSeller)
|
||||
end
|
||||
end
|
||||
|
||||
function AuctionScanManager.PrepareForBidOrBuyout(self, index, subRow, noSeller, quantity, itemBuyout)
|
||||
if TSM.IsWowClassic() then
|
||||
return subRow:EqualsIndex(index, noSeller)
|
||||
else
|
||||
local itemString = subRow:GetItemString()
|
||||
if ItemInfo.IsCommodity(itemString) then
|
||||
local future = AuctionHouseWrapper.StartCommoditiesPurchase(ItemString.ToId(itemString), quantity, itemBuyout)
|
||||
if not future then
|
||||
return false
|
||||
end
|
||||
return true, future
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AuctionScanManager.PlaceBidOrBuyout(self, index, bidBuyout, subRow, quantity)
|
||||
if TSM.IsWowClassic() then
|
||||
PlaceAuctionBid("list", index, bidBuyout)
|
||||
return true
|
||||
else
|
||||
local itemString = subRow:GetItemString()
|
||||
local future = nil
|
||||
if ItemInfo.IsCommodity(itemString) then
|
||||
local itemId = ItemString.ToId(itemString)
|
||||
future = AuctionHouseWrapper.ConfirmCommoditiesPurchase(itemId, quantity)
|
||||
else
|
||||
local _, auctionId = subRow:GetListingInfo()
|
||||
future = AuctionHouseWrapper.PlaceBid(auctionId, bidBuyout)
|
||||
quantity = 1
|
||||
end
|
||||
if not future then
|
||||
return false
|
||||
end
|
||||
-- TODO: return this future and record the buyout once the future is done
|
||||
future:Cancel()
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function AuctionScanManager.GetProgress(self)
|
||||
local numQueries = self:GetNumQueries()
|
||||
if self._queriesScanned == numQueries then
|
||||
return 1
|
||||
end
|
||||
local currentQuery = self._queries[self._queriesScanned + 1]
|
||||
local searchProgress = nil
|
||||
if not self._queryDidBrowse or TSM.IsWowClassic() then
|
||||
searchProgress = 0
|
||||
else
|
||||
searchProgress = currentQuery:GetSearchProgress() * (1 - BROWSE_PROGRESS) + BROWSE_PROGRESS
|
||||
end
|
||||
local queryStep = 1 / numQueries
|
||||
local progress = min((self._queriesScanned + searchProgress) * queryStep, 1)
|
||||
return progress, self._paused
|
||||
end
|
||||
|
||||
function AuctionScanManager.Cancel(self)
|
||||
self._cancelled = true
|
||||
if self._scanQuery then
|
||||
self._scanQuery:CancelBrowseOrSearch()
|
||||
self._scanQuery = nil
|
||||
end
|
||||
end
|
||||
|
||||
function AuctionScanManager.SetPaused(self, paused)
|
||||
self._shouldPause = paused
|
||||
if self._scanQuery then
|
||||
self._scanQuery:CancelBrowseOrSearch()
|
||||
self._scanQuery = nil
|
||||
end
|
||||
end
|
||||
|
||||
function AuctionScanManager.GetNumItems(self)
|
||||
return self._numItems
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- Private Class Methods
|
||||
-- ============================================================================
|
||||
|
||||
function AuctionScanManager._AddQuery(self, query)
|
||||
query:SetResolveSellers(self._resolveSellers)
|
||||
query:SetCallback(self._queryCallback)
|
||||
tinsert(self._queries, query)
|
||||
end
|
||||
|
||||
function AuctionScanManager._IsCancelled(self)
|
||||
return self._cancelled
|
||||
end
|
||||
|
||||
function AuctionScanManager._Pause(self)
|
||||
if not self._shouldPause then
|
||||
return
|
||||
end
|
||||
self._paused = true
|
||||
self:_NotifyProgressUpdate()
|
||||
if self._currentSearchChangedCallback then
|
||||
self:_currentSearchChangedCallback()
|
||||
end
|
||||
while self._shouldPause do
|
||||
Threading.Yield(true)
|
||||
end
|
||||
self._paused = false
|
||||
self:_NotifyProgressUpdate()
|
||||
if self._currentSearchChangedCallback then
|
||||
self:_currentSearchChangedCallback()
|
||||
end
|
||||
end
|
||||
|
||||
function AuctionScanManager._NotifyProgressUpdate(self)
|
||||
if self._onProgressUpdateHandler then
|
||||
self:_onProgressUpdateHandler()
|
||||
end
|
||||
end
|
||||
|
||||
function AuctionScanManager._ProcessQuery(self, query)
|
||||
local prevMaxBrowseId = 0
|
||||
for _, row in query:BrowseResultsIterator() do
|
||||
prevMaxBrowseId = max(prevMaxBrowseId, row:GetMinBrowseId())
|
||||
end
|
||||
|
||||
-- run the browse query
|
||||
self._queryDidBrowse = false
|
||||
while not self:_DoBrowse(query) do
|
||||
if self._shouldPause then
|
||||
-- this browse failed due to a pause request, so try again after we're resumed
|
||||
self:_Pause()
|
||||
-- wipe the browse results since we're going to do another search
|
||||
query:WipeBrowseResults()
|
||||
else
|
||||
return false, 0
|
||||
end
|
||||
end
|
||||
self._queryDidBrowse = true
|
||||
self:_NotifyProgressUpdate()
|
||||
|
||||
local numNewResults = 0
|
||||
if TSM.IsWowClassic() then
|
||||
for _, row in query:BrowseResultsIterator() do
|
||||
if row:GetMinBrowseId() > prevMaxBrowseId then
|
||||
numNewResults = numNewResults + row:GetNumSubRows()
|
||||
end
|
||||
end
|
||||
return true, numNewResults
|
||||
end
|
||||
|
||||
local rows = Threading.AcquireSafeTempTable()
|
||||
for baseItemString, row in query:BrowseResultsIterator() do
|
||||
rows[baseItemString] = row
|
||||
end
|
||||
while true do
|
||||
local baseItemString, row = nil, nil
|
||||
if self._nextSearchItemFunction then
|
||||
baseItemString = self._nextSearchItemFunction()
|
||||
row = baseItemString and rows[baseItemString]
|
||||
end
|
||||
if not row then
|
||||
baseItemString, row = next(rows)
|
||||
end
|
||||
if not row then
|
||||
break
|
||||
end
|
||||
rows[baseItemString] = nil
|
||||
if self._currentSearchChangedCallback then
|
||||
self:_currentSearchChangedCallback(baseItemString)
|
||||
end
|
||||
-- store all the existing auctionIds so we can see what changed
|
||||
local prevAuctionIds = Threading.AcquireSafeTempTable()
|
||||
for _, subRow in row:SubRowIterator() do
|
||||
local _, auctionId = subRow:GetListingInfo()
|
||||
assert(not prevAuctionIds[auctionId])
|
||||
prevAuctionIds[auctionId] = true
|
||||
end
|
||||
-- send the query for this item
|
||||
while not self:_DoSearch(query, row) do
|
||||
if self._shouldPause then
|
||||
-- this search failed due to a pause request, so try again after we're resumed
|
||||
self:_Pause()
|
||||
-- wipe the search results since we're going to do another search
|
||||
row:WipeSearchResults()
|
||||
else
|
||||
Threading.ReleaseSafeTempTable(prevAuctionIds)
|
||||
Threading.ReleaseSafeTempTable(rows)
|
||||
return false, numNewResults
|
||||
end
|
||||
end
|
||||
|
||||
local numSubRows = row:GetNumSubRows()
|
||||
for _, subRow in row:SubRowIterator() do
|
||||
local _, auctionId = subRow:GetListingInfo()
|
||||
if not prevAuctionIds[auctionId] then
|
||||
numNewResults = numNewResults + 1
|
||||
end
|
||||
end
|
||||
Threading.ReleaseSafeTempTable(prevAuctionIds)
|
||||
if numSubRows == 0 then
|
||||
-- remove this row since there are no search results
|
||||
query:RemoveResultRow(row)
|
||||
end
|
||||
|
||||
self:_NotifyProgressUpdate()
|
||||
self:_Pause()
|
||||
Threading.Yield()
|
||||
end
|
||||
Threading.ReleaseSafeTempTable(rows)
|
||||
return true, numNewResults
|
||||
end
|
||||
|
||||
function AuctionScanManager._DoBrowse(self, query, ...)
|
||||
return self:_DoBrowseSearchHelper(query, query:Browse(...))
|
||||
end
|
||||
|
||||
function AuctionScanManager._DoSearch(self, query, ...)
|
||||
return self:_DoBrowseSearchHelper(query, query:Search(...))
|
||||
end
|
||||
|
||||
function AuctionScanManager._DoBrowseSearchHelper(self, query, future)
|
||||
if not future then
|
||||
return false
|
||||
end
|
||||
self._scanQuery = query
|
||||
local result = Threading.WaitForFuture(future)
|
||||
self._scanQuery = nil
|
||||
Threading.Yield()
|
||||
return result
|
||||
end
|
||||
|
||||
function AuctionScanManager._FindAuctionThreaded(self, row, noSeller)
|
||||
self._cancelled = false
|
||||
-- make sure we're not in the middle of a query where the results are going to change on us
|
||||
Threading.WaitForFunction(CanSendAuctionQuery)
|
||||
|
||||
-- search the current page for the auction
|
||||
if self:_FindAuctionOnCurrentPage(row, noSeller) then
|
||||
Log.Info("Found on current page")
|
||||
return self._findResult
|
||||
end
|
||||
|
||||
-- search for the item
|
||||
local page, maxPage = 0, nil
|
||||
while true do
|
||||
-- query the AH
|
||||
if self._findQuery then
|
||||
self._findQuery:Release()
|
||||
end
|
||||
local itemString = row:GetItemString()
|
||||
local level = ItemInfo.GetMinLevel(itemString)
|
||||
local quality = ItemInfo.GetQuality(itemString)
|
||||
assert(level and quality)
|
||||
self._findQuery = Query.Get()
|
||||
:SetStr(ItemInfo.GetName(itemString), true)
|
||||
:SetQualityRange(quality, quality)
|
||||
:SetLevelRange(level, level)
|
||||
:SetClass(ItemInfo.GetClassId(itemString), ItemInfo.GetSubClassId(itemString))
|
||||
:SetItems(itemString)
|
||||
:SetResolveSellers(not noSeller)
|
||||
:SetPage(page)
|
||||
local filterSuccess = self:_DoBrowse(self._findQuery)
|
||||
if self._findQuery then
|
||||
self._findQuery:Release()
|
||||
self._findQuery = nil
|
||||
end
|
||||
if not filterSuccess then
|
||||
break
|
||||
end
|
||||
-- search this page for the row
|
||||
if self:_FindAuctionOnCurrentPage(row, noSeller) then
|
||||
Log.Info("Found auction (%d)", page)
|
||||
return self._findResult
|
||||
elseif self:_IsCancelled() then
|
||||
break
|
||||
end
|
||||
|
||||
local numPages = ceil(select(2, GetNumAuctionItems("list")) / NUM_AUCTION_ITEMS_PER_PAGE)
|
||||
local canBeLater = private.FindAuctionCanBeOnLaterPage(row)
|
||||
maxPage = maxPage or numPages - 1
|
||||
if not canBeLater and page < maxPage then
|
||||
maxPage = page
|
||||
end
|
||||
if canBeLater and page < maxPage then
|
||||
Log.Info("Trying next page (%d)", page + 1)
|
||||
page = page + 1
|
||||
else
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AuctionScanManager._FindAuctionOnCurrentPage(self, subRow, noSeller)
|
||||
local found = false
|
||||
for i = 1, GetNumAuctionItems("list") do
|
||||
if subRow:EqualsIndex(i, noSeller) then
|
||||
tinsert(self._findResult, i)
|
||||
found = true
|
||||
end
|
||||
end
|
||||
return found
|
||||
end
|
||||
|
||||
function AuctionScanManager._FindAuctionThreaded83(self, findSubRow, noSeller)
|
||||
assert(findSubRow:IsSubRow())
|
||||
self._cancelled = false
|
||||
noSeller = noSeller or findSubRow:IsCommodity()
|
||||
|
||||
local row = findSubRow:GetResultRow()
|
||||
local findHash, findHashNoSeller = findSubRow:GetHashes()
|
||||
|
||||
if not self:_DoSearch(row:GetQuery(), row, false) then
|
||||
return nil
|
||||
end
|
||||
local result = nil
|
||||
-- first try to find a subRow with a full matching hash
|
||||
for _, subRow in row:SubRowIterator() do
|
||||
local quantity, numAuctions = subRow:GetQuantities()
|
||||
local hash = subRow:GetHashes()
|
||||
if hash == findHash then
|
||||
result = (result or 0) + quantity * numAuctions
|
||||
end
|
||||
end
|
||||
if result then
|
||||
return result
|
||||
end
|
||||
-- next try to find the first subRow with a matching no-seller hash
|
||||
local firstHash = nil
|
||||
for _, subRow in row:SubRowIterator() do
|
||||
local quantity, numAuctions = subRow:GetQuantities()
|
||||
local hash, hashNoSeller = subRow:GetHashes()
|
||||
if (not firstHash or hash == firstHash) and hashNoSeller == findHashNoSeller then
|
||||
firstHash = hash
|
||||
result = (result or 0) + quantity * numAuctions
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- Private Helper Functions
|
||||
-- ============================================================================
|
||||
|
||||
function private.NewQueryCallback(query, self)
|
||||
self:_AddQuery(query)
|
||||
end
|
||||
|
||||
function private.FindAuctionCanBeOnLaterPage(row)
|
||||
local pageAuctions = GetNumAuctionItems("list")
|
||||
if pageAuctions == 0 then
|
||||
-- there are no auctions on this page, so it cannot be on a later one
|
||||
return false
|
||||
end
|
||||
local _, _, stackSize, _, _, _, _, _, _, buyout, _, _, _, seller, sellerFull = GetAuctionItemInfo("list", pageAuctions)
|
||||
|
||||
local itemBuyout = (buyout > 0) and floor(buyout / stackSize) or 0
|
||||
local _, rowItemBuyout = row:GetBuyouts()
|
||||
if rowItemBuyout > itemBuyout then
|
||||
-- item must be on a later page since it would be sorted after the last auction on this page
|
||||
return true
|
||||
elseif rowItemBuyout < itemBuyout then
|
||||
-- item cannot be on a later page since it would be sorted before the last auction on this page
|
||||
return false
|
||||
end
|
||||
|
||||
local rowStackSize = row:GetQuantities()
|
||||
if rowStackSize > stackSize then
|
||||
-- item must be on a later page since it would be sorted after the last auction on this page
|
||||
return true
|
||||
elseif rowStackSize < stackSize then
|
||||
-- item cannot be on a later page since it would be sorted before the last auction on this page
|
||||
return false
|
||||
end
|
||||
|
||||
seller = private.FixSellerName(seller, sellerFull) or "?"
|
||||
local rowSeller = row:GetOwnerInfo()
|
||||
if rowSeller > seller then
|
||||
-- item must be on a later page since it would be sorted after the last auction on this page
|
||||
return true
|
||||
elseif rowSeller < seller then
|
||||
-- item cannot be on a later page since it would be sorted before the last auction on this page
|
||||
return false
|
||||
end
|
||||
|
||||
-- all the things we are sorting on are the same, so the auction could be on a later page
|
||||
return true
|
||||
end
|
||||
|
||||
function private.FixSellerName(seller, sellerFull)
|
||||
local realm = GetRealmName()
|
||||
if sellerFull and strjoin("-", seller, realm) ~= sellerFull then
|
||||
return sellerFull
|
||||
else
|
||||
return seller
|
||||
end
|
||||
end
|
||||
|
||||
function private.QueryIteratorHelper(tbl, index)
|
||||
index = index + 1
|
||||
if index > #tbl then
|
||||
return
|
||||
end
|
||||
return index, tbl[index]
|
||||
end
|
||||
Reference in New Issue
Block a user