vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 --[[
2 Auctioneer Addon for World of Warcraft(tm).
3 Version: 3.9.0.1000 (Kangaroo)
4 Revision: $Id: AucBidManager.lua 927 2006-07-06 02:15:28Z mentalpower $
5  
6 BidManager - manages bid requests in the AH
7  
8 License:
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13  
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18  
19 You should have received a copy of the GNU General Public License
20 along with this program(see GPL.txt); if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 --]]
23  
24 -------------------------------------------------------------------------------
25 -- Data Members
26 -------------------------------------------------------------------------------
27  
28 -- Queue of bid requests to be worked on
29 local LastRequest;
30 local RequestQueue = {};
31 local ProcessingRequestQueue = false;
32  
33 -- Bid queue actions
34 local BID_AUCTION = "bid";
35 local BUYOUT_AUCTION = "buyout";
36  
37 -- Parameters of QueryAuctionItems() last time it was called.
38 local CurrentSearchParams =
39 {
40 name = nil;
41 minLevel = nil;
42 maxLevel = nil;
43 invTypeIndex = nil;
44 classIndex = nil;
45 subclassIndex = nil;
46 page = nil;
47 isUsable = nil;
48 qualityIndex = nil;
49 queryTime = nil; -- Time that the query was made or the last response was received
50 queryResponse = true; -- Flag indicates if any response has been received
51 queryComplete = true; -- Flag indicates if the entire response has been received
52 targetCountForPage = nil; -- Number of items expected on the page (nil for unknown)
53 };
54  
55 -- Queue of bids submitted to the server, but not yet accepted or rejected
56 local PendingBids = {};
57  
58 -- Function hooks that are used when processing requests
59 local Original_CanSendAuctionQuery;
60 local Original_AuctionFrameBrowse_OnEvent;
61 local Original_AuctionFrameBrowse_Update;
62  
63 -- Result codes for bid requests.
64 BidResultCodes = {}
65 BidResultCodes["BidAccepted"] = 0;
66 BidResultCodes["ItemNotFound"] = 1;
67 BidResultCodes["NotEnoughMoney"] = 2;
68 BidResultCodes["OwnAuction"] = 3;
69 BidResultCodes["AlreadyHigherBid"] = 4;
70 BidResultCodes["AlreadyHighBidder"] = 5;
71 BidResultCodes["CurrentBidLower"] = 6;
72 BidResultCodes["MaxBidsReached"] = 7;
73  
74 -------------------------------------------------------------------------------
75 -- Function Prototypes
76 -------------------------------------------------------------------------------
77 local addPlayerToAccount;
78 local isPlayerOnAccount;
79 local isBidInProgress;
80 local addPendingBid;
81 local removePendingBid;
82 local placeAuctionBidHook;
83 local onBidResponse;
84 local isQueryInProgress;
85 local queryAuctionItemsHook;
86 local checkQueryComplete;
87 local addRequestToQueue;
88 local removeRequestFromQueue;
89 local isProcessingRequest;
90 local getRequestCount;
91 local beginProcessingRequestQueue;
92 local endProcessingRequestQueue;
93 local processRequestQueue;
94 local processPage;
95 local nilSafe;
96 local boolString;
97 local chatPrint;
98 local debugPrint;
99 local bidAuction;
100 local dumpState;
101  
102 -------------------------------------------------------------------------------
103 -------------------------------------------------------------------------------
104 function AucBidManagerFrame_OnLoad()
105 this:RegisterEvent("ADDON_LOADED");
106 this:RegisterEvent("AUCTION_ITEM_LIST_UPDATE");
107 this:RegisterEvent("AUCTION_HOUSE_CLOSED");
108  
109 Stubby.RegisterFunctionHook("PlaceAuctionBid", -50, placeAuctionBidHook)
110 Stubby.RegisterFunctionHook("QueryAuctionItems", -50, queryAuctionItemsHook)
111 end
112  
113 -------------------------------------------------------------------------------
114 -------------------------------------------------------------------------------
115 function AucBidManagerFrame_OnEvent(event)
116 if (event == "ADDON_LOADED" and string.lower(arg1) == "auctioneer") then
117 addPlayerToAccount(UnitName("player"));
118 this:UnregisterEvent("ADDON_LOADED");
119 elseif (event == "AUCTION_ITEM_LIST_UPDATE") then
120 debugPrint(event);
121 checkQueryComplete();
122 elseif (event == "CHAT_MSG_SYSTEM" and arg1) then
123 debugPrint(event);
124 if (arg1) then debugPrint(" "..arg1) end;
125 if (arg1 == ERR_AUCTION_BID_PLACED) then
126 onBidResponse(BidResultCodes["BidAccepted"]);
127 end
128 elseif (event == "UI_ERROR_MESSAGE" and arg1) then
129 debugPrint(event);
130 if (arg1) then debugPrint(" "..arg1) end;
131 if (arg1 == ERR_ITEM_NOT_FOUND) then
132 onBidResponse(BidResultCodes["ItemNotFound"]);
133 elseif (arg1 == ERR_NOT_ENOUGH_MONEY) then
134 onBidResponse(BidResultCodes["NotEnoughMoney"]);
135 elseif (arg1 == ERR_AUCTION_BID_OWN) then
136 onBidResponse(BidResultCodes["OwnAuction"]);
137 elseif (arg1 == ERR_AUCTION_HIGHER_BID) then
138 onBidResponse(BidResultCodes["AlreadyHigherBid"]);
139 end
140 elseif (event == "AUCTION_HOUSE_CLOSED") then
141 endProcessingRequestQueue();
142 end
143 end
144  
145 -------------------------------------------------------------------------------
146 -------------------------------------------------------------------------------
147 function AucBidManagerFrame_OnUpdate()
148 processRequestQueue();
149 end
150  
151 -------------------------------------------------------------------------------
152 -------------------------------------------------------------------------------
153 function AucBidManager_CanSendAuctionQuery()
154 -- Intentionally empty; don't allow the auction UI to update while we're processing requests
155 return false;
156 end
157  
158 -------------------------------------------------------------------------------
159 -------------------------------------------------------------------------------
160 function AucBidManager_AuctionFrameBrowse_OnEvent()
161 -- Intentionally empty; don't allow the auction UI to update while we're processing requests
162 end
163  
164 -------------------------------------------------------------------------------
165 -------------------------------------------------------------------------------
166 function AucBidManager_AuctionFrameBrowse_Update()
167 -- Intentionally empty; don't allow the auction UI to update while we're processing requests
168 end
169  
170 -------------------------------------------------------------------------------
171 -- Adds a player to the list of players on the current account.
172 -------------------------------------------------------------------------------
173 function addPlayerToAccount(player)
174 -- List of players on the same account as the current player (including the
175 -- current player). Auctions owned by these players cannot be bid on.
176 if (not AuctionConfig.players) then AuctionConfig.players = {}; end
177 if (not isPlayerOnAccount(player)) then
178 table.insert(AuctionConfig.players, player);
179 end
180 end
181  
182 -------------------------------------------------------------------------------
183 -- Checks if a player is on the same account as the current player.
184 -------------------------------------------------------------------------------
185 function isPlayerOnAccount(player)
186 if (not AuctionConfig.players) then AuctionConfig.players = {}; end
187 for _, p in pairs(AuctionConfig.players) do
188 if (p == player) then
189 return true;
190 end
191 end
192 return false;
193 end
194  
195 -------------------------------------------------------------------------------
196 -- Returns true if a bid request is in flight to the server
197 -------------------------------------------------------------------------------
198 function isBidInProgress()
199 return (table.getn(PendingBids) > 0);
200 end
201  
202 -------------------------------------------------------------------------------
203 -- Adds a pending bid to the queue.
204 -------------------------------------------------------------------------------
205 function addPendingBid(name, count, bid, owner, request)
206 -- Add a pending bid to the queue.
207 local pendingBid = {};
208 pendingBid.name = name;
209 pendingBid.count = count;
210 pendingBid.bid = bid;
211 pendingBid.owner = owner;
212 pendingBid.request = request;
213 table.insert(PendingBids, pendingBid);
214 debugPrint("addPendingBid() - Added pending bid");
215 if (request) then
216 debugPrint("addPendingBid() - Associated request with pending bid "..table.getn(PendingBids));
217 end
218  
219 -- Register for the response events if this is the first pending bid.
220 if (table.getn(PendingBids) == 1) then
221 debugPrint("addPendingBid() - Registering for CHAT_MSG_SYSTEM and UI_ERROR_MESSAGE");
222 AucBidManagerFrame:RegisterEvent("CHAT_MSG_SYSTEM");
223 AucBidManagerFrame:RegisterEvent("UI_ERROR_MESSAGE");
224 end
225 end
226  
227 -------------------------------------------------------------------------------
228 -- Removes the pending bid from the queue.
229 -------------------------------------------------------------------------------
230 function removePendingBid()
231 if (table.getn(PendingBids) > 0) then
232 -- Remove the first pending bid.
233 local bid = PendingBids[1];
234 table.remove(PendingBids, 1);
235 debugPrint("removePendingBid() - Removed pending bid");
236  
237 -- Unregister for the response events if this is the last pending bid.
238 if (table.getn(PendingBids) == 0) then
239 debugPrint("removePendingBid() - Unregistering for CHAT_MSG_SYSTEM and UI_ERROR_MESSAGE");
240 AucBidManagerFrame:UnregisterEvent("CHAT_MSG_SYSTEM");
241 AucBidManagerFrame:UnregisterEvent("UI_ERROR_MESSAGE");
242 end
243  
244 return bid;
245 end
246  
247 -- No pending bid to remove!
248 return nil;
249 end
250  
251 -------------------------------------------------------------------------------
252 -- Called before PlaceAuctionBid()
253 -------------------------------------------------------------------------------
254 function placeAuctionBidHook(_, _, listType, index, bid, request)
255 local name, texture, count, quality, canUse, level, minBid, minIncrement, buyoutPrice, bidAmount, highBidder, owner = GetAuctionItemInfo(listType, index);
256 if (name and count and bid) then
257 addPendingBid(name, count, bid, owner, request);
258 return "setparams", {listType, index, bid};
259 else
260 debugPrint("PlaceAuctionBid() - Ignoring bid");
261 return "abort";
262 end
263 end
264  
265 -------------------------------------------------------------------------------
266 -- Called whenever a response to a bid is received
267 -------------------------------------------------------------------------------
268 function onBidResponse(result)
269 if (table.getn(PendingBids) > 0) then
270 -- We always assume the bid response is for the next bid in PendingBids.
271 local bid = removePendingBid();
272  
273 -- If there is an associated request, add our result to it.
274 local request = bid.request;
275 if (request) then
276 debugPrint("Found request associated with bid");
277 if (result == BidResultCodes["BidAccepted"]) then
278 table.insert(request.results, result);
279 if (request.bid == request.buyout) then
280 local output = string.format(_AUCT('FrmtBoughtAuction'), request.name, request.count);
281 chatPrint(output);
282  
283 else
284 local output = string.format(_AUCT('FrmtBidAuction'), request.name, request.count);
285 chatPrint(output);
286 end
287  
288 elseif (result == BidResultCodes["ItemNotFound"]) then
289 -- nothing to do
290  
291 elseif (result == BidResultCodes["NotEnoughMoney"]) then
292 table.insert(request.results, result);
293 local output = string.format(_AUCT('FrmtNotEnoughMoney'), request.name, request.count);
294 chatPrint(output);
295  
296 elseif (result == BidResultCodes["OwnAuction"]) then
297 table.insert(request.results, result);
298 local output = string.format(_AUCT('FrmtSkippedBiddingOnOwnAuction'), request.name, request.count);
299 chatPrint(output);
300  
301 elseif (result == BidResultCodes["AlreadyHigherBid"]) then
302 if (request.bid ~= request.buyout) then
303 table.insert(request.results, result);
304 local output = string.format(_AUCT('FrmtSkippedAuctionWithHigherBid'), request.name, request.count);
305 chatPrint(output);
306 else
307 debugPrint("Attempted to buyout the same auction");
308 end
309 end
310 else
311 debugPrint("Did not find request associated with bid");
312 end
313  
314 -- Process the bid result .
315 if (result == BidResultCodes["BidAccepted"] and request) then
316 -- Check if there is a corresponding request and upate it to
317 -- reflect the successful bid.
318 if (request) then
319 request.bidCount = request.bidCount + 1;
320  
321 -- Increment the request's current index if the auction was not bought out.
322 if (request.bid ~= request.buyout) then
323 request.currentIndex = request.currentIndex + 1;
324 debugPrint("Incrementing the request's currentIndex to "..request.currentIndex);
325  
326 end
327 end
328  
329 elseif (result ~= BidResultCodes["BidAccepted"]) then
330 -- We were expecting the list to update after our bid/buyout, but
331 -- our bid/buyout failed so we won't be getting an update.
332 CurrentSearchParams.queryComplete = true;
333 CurrentSearchParams.queryResponse = true;
334 CurrentSearchParams.targetCountForPage = nil;
335  
336 -- Skip over the auction we failed to bid on.
337 if (request) then
338 request.currentIndex = request.currentIndex + 1;
339 debugPrint("Incrementing the request's currentIndex to "..request.currentIndex);
340 end
341  
342 if (result == BidResultCodes["OwnAuction"] and bid.owner) then
343 -- We tried bidding on our own auction! Blizzard doesn't
344 -- allow bids from any player on the account that posted
345 -- the auction. Therefore we keep a dynamic list of all
346 -- of these failures so we can avoid these auctions in the
347 -- future.
348 addPlayerToAccount(bid.owner);
349 end
350 end
351  
352 else
353 -- We got out of sync somehow... this indicates a bug in how we determine
354 -- the results of bid requests.
355 chatPrint(_AUCT('FrmtBidQueueOutOfSync'));
356 end
357 end
358  
359 -------------------------------------------------------------------------------
360 -- Returns true if a query is in progress
361 -------------------------------------------------------------------------------
362 function isQueryInProgress()
363 return (not CurrentSearchParams.queryComplete);
364 end
365  
366 -------------------------------------------------------------------------------
367 -- Wrapper around CanSendAuctionQuery() that always calls the Blizzard version.
368 -------------------------------------------------------------------------------
369 function canSendAuctionQuery()
370 if (Original_CanSendAuctionQuery) then
371 return Original_CanSendAuctionQuery();
372 end
373 return CanSendAuctionQuery();
374 end
375  
376 -------------------------------------------------------------------------------
377 -- Called before QueryAuctionItems()
378 -------------------------------------------------------------------------------
379 function queryAuctionItemsHook(_, _, name, minLevel, maxLevel, invTypeIndex, classIndex, subclassIndex, page, isUsable, qualityIndex)
380 if (not Auctioneer.Scanning.IsScanningRequested and canSendAuctionQuery()) then
381 CurrentSearchParams.name = name;
382 CurrentSearchParams.minLevel = minLevel;
383 CurrentSearchParams.maxLevel = maxLevel;
384 CurrentSearchParams.invTypeIndex = invTypeIndex;
385 CurrentSearchParams.classIndex = classIndex;
386 CurrentSearchParams.subclassIndex = subclassIndex;
387 CurrentSearchParams.page = page;
388 CurrentSearchParams.isUsable = isUsable;
389 CurrentSearchParams.qualityIndex = qualityIndex;
390 CurrentSearchParams.queryTime = time();
391 CurrentSearchParams.queryResponse = false;
392 CurrentSearchParams.queryComplete = false;
393 CurrentSearchParams.targetCountForPage = nil;
394 debugPrint("queryAuctionItemsHook()");
395  
396 else
397 CurrentSearchParams.name = nil;
398 CurrentSearchParams.minLevel = nil;
399 CurrentSearchParams.maxLevel = nil;
400 CurrentSearchParams.invTypeIndex = nil;
401 CurrentSearchParams.classIndex = nil;
402 CurrentSearchParams.subclassIndex = nil;
403 CurrentSearchParams.page = nil;
404 CurrentSearchParams.isUsable = nil;
405 CurrentSearchParams.qualityIndex = nil;
406 CurrentSearchParams.queryTime = time();
407 CurrentSearchParams.queryResponse = true;
408 CurrentSearchParams.queryComplete = true;
409 CurrentSearchParams.targetCountForPage = nil;
410 debugPrint("queryAuctionItemsHook() - ignoring");
411 end
412  
413 -- Toss the information about the last request processed.
414 LastRequest = nil;
415 end
416  
417 -------------------------------------------------------------------------------
418 -- Checks a query to see if its complete. Often times the owner information
419 -- of auctions are missing at first. Asking for it triggers another update
420 -- of the auction list.
421 -------------------------------------------------------------------------------
422 function checkQueryComplete()
423 if (not CurrentSearchParams.queryComplete) then
424 -- Get the number of auctions on the page.
425 local lastIndexOnPage, totalAuctions = GetNumAuctionItems("list");
426 debugPrint("LastIndexOnPage = "..lastIndexOnPage);
427 debugPrint("TotalAuctions = "..totalAuctions);
428  
429 if (CurrentSearchParams.targetCountForPage == nil or CurrentSearchParams.targetCountForPage == lastIndexOnPage) then
430 -- Assume true until otherwise proven false.
431 CurrentSearchParams.queryTime = time();
432 CurrentSearchParams.queryResponse = true;
433 CurrentSearchParams.queryComplete = true;
434 for indexOnPage = 1, lastIndexOnPage do
435 local _,_,_,_,_,_,_,_,_,_,_, owner = GetAuctionItemInfo("list", indexOnPage);
436 if (owner == nil) then
437 -- No dice... there are more updates coming...
438 CurrentSearchParams.queryComplete = false;
439 break;
440 end
441 end
442 if (CurrentSearchParams.queryComplete) then
443 debugPrint("checkQueryComplete() - true");
444 else
445 debugPrint("checkQueryComplete() - false (waiting for owner information on auctions)");
446 end
447 else
448 debugPrint("checkQueryComplete() - false (waiting for "..CurrentSearchParams.targetCountForPage.." auctions on page)");
449 end
450 end
451 end
452  
453 -------------------------------------------------------------------------------
454 -- Adds a request to the queue.
455 -------------------------------------------------------------------------------
456 function addRequestToQueue(request)
457 -- Add the request state information
458 request.bidAttempts = 0;
459 request.bidCount = 0;
460 request.currentPage = 0;
461 request.currentIndex = 1;
462 request.continuation = false;
463 request.results = {};
464  
465 -- Check if the previous request is the same as this request. If so we
466 -- want to pickup where the last request left off.
467 if (table.getn(RequestQueue) == 0 and
468 LastRequest ~= nil and
469 LastRequest.id == request.id and
470 LastRequest.rprop == request.rprop and
471 LastRequest.enchant == request.enchant and
472 LastRequest.name == request.name and
473 LastRequest.count == request.count and
474 LastRequest.min == request.min and
475 LastRequest.buyout == request.buyout and
476 LastRequest.unique == request.unique and
477 LastRequest.bid == request.bid) then
478 request.currentPage = LastRequest.currentPage;
479 request.currentIndex = LastRequest.currentIndex;
480 request.continuation = true;
481 end
482  
483 -- Add the request to the queue.
484 table.insert(RequestQueue, request);
485 debugPrint("Added request to queue: "..request.name..", "..request.count..", "..nilSafe(request.buyout)..", "..nilSafe(request.bid));
486 end
487  
488 -------------------------------------------------------------------------------
489 -- Removes a request at the head of the queue.
490 -------------------------------------------------------------------------------
491 function removeRequestFromQueue()
492 if (table.getn(RequestQueue) > 0) then
493 -- Remove the request from the queue.
494 local request = RequestQueue[1];
495 table.remove(RequestQueue, 1);
496 debugPrint("Removed request from queue: "..request.name..", "..request.count..", "..nilSafe(request.buyout)..", "..nilSafe(request.bid));
497  
498 -- Make the callback, if requested.
499 local callback = request.callback;
500 if (callback and callback.func) then
501 callback.func(callback.param, request);
502 end
503  
504 -- Inform the user if no auctions were found.
505 if (table.getn(request.results) == 0) then
506 if (request.continuation) then
507 local output = string.format(_AUCT('FrmtNoMoreAuctionsFound'), request.name, request.count);
508 chatPrint(output);
509 else
510 local output = string.format(_AUCT('FrmtNoAuctionsFound'), request.name, request.count);
511 chatPrint(output);
512 end
513 end
514  
515 -- Check if the next request is the same as the previous. If so we
516 -- want to pickup where the last request left off.
517 if (LastRequest ~= nil and table.getn(RequestQueue) > 0) then
518 local nextRequest = RequestQueue[1];
519 if (LastRequest.id == nextRequest.id and
520 LastRequest.rprop == nextRequest.rprop and
521 LastRequest.enchant == nextRequest.enchant and
522 LastRequest.name == nextRequest.name and
523 LastRequest.count == nextRequest.count and
524 LastRequest.min == nextRequest.min and
525 LastRequest.buyout == nextRequest.buyout and
526 LastRequest.unique == nextRequest.unique and
527 LastRequest.bid == nextRequest.bid) then
528 nextRequest.currentPage = LastRequest.currentPage;
529 nextRequest.currentIndex = LastRequest.currentIndex;
530 nextRequest.continuation = true;
531 end
532 end
533 end
534 end
535  
536 -------------------------------------------------------------------------------
537 -- Checks if the BidManager is currently working on a request.
538 -------------------------------------------------------------------------------
539 function isProcessingRequest()
540 return ProcessingRequestQueue;
541 end
542  
543 -------------------------------------------------------------------------------
544 -- Gets the number of pending requests.
545 -------------------------------------------------------------------------------
546 function getRequestCount()
547 return table.getn(RequestQueue);
548 end
549  
550 -------------------------------------------------------------------------------
551 -- Starts processing the request queue if possible. Returns true if started.
552 -------------------------------------------------------------------------------
553 function beginProcessingRequestQueue()
554 if (not ProcessingRequestQueue and
555 AuctionFrame and AuctionFrame:IsVisible() and
556 table.getn(RequestQueue) > 0 and
557 not Auctioneer.Scanning.IsScanningRequested and
558 not isQueryInProgress() and
559 not isBidInProgress()) then
560  
561 ProcessingRequestQueue = true;
562 AucBidManagerFrame:Show();
563 debugPrint("Begin processing the bid queue");
564  
565 -- Hook the functions to disable the Browse UI
566 if (not Original_CanSendAuctionQuery) then
567 Original_CanSendAuctionQuery = CanSendAuctionQuery;
568 CanSendAuctionQuery = AucBidManager_CanSendAuctionQuery;
569 end
570 if (not Original_AuctionFrameBrowse_OnEvent) then
571 Original_AuctionFrameBrowse_OnEvent = AuctionFrameBrowse_OnEvent;
572 AuctionFrameBrowse_OnEvent = AucBidManager_AuctionFrameBrowse_OnEvent;
573 end
574 if (not Original_AuctionFrameBrowse_Update) then
575 Original_AuctionFrameBrowse_Update = AuctionFrameBrowse_Update;
576 AuctionFrameBrowse_Update = AucBidManager_AuctionFrameBrowse_Update;
577 end
578  
579 -- Hide the UI from any current results, show the no results text so we can use it
580 BrowseNoResultsText:Show();
581 BrowseNoResultsText:SetText(_AUCT('UiProcessingBidRequests'));
582 for iButton = 1, NUM_BROWSE_TO_DISPLAY do
583 button = getglobal("BrowseButton"..iButton);
584 button:Hide();
585 end
586 BrowsePrevPageButton:Hide();
587 BrowseNextPageButton:Hide();
588 BrowseSearchCountText:Hide();
589 BrowseBidButton:Disable();
590 BrowseBuyoutButton:Disable();
591 end
592 return ProcessingRequestQueue;
593 end
594  
595 -------------------------------------------------------------------------------
596 -- Ends processing the request queue
597 -------------------------------------------------------------------------------
598 function endProcessingRequestQueue()
599 if (ProcessingRequestQueue) then
600 ProcessingRequestQueue = false;
601 AucBidManagerFrame:Hide();
602 debugPrint("End processing the bid queue");
603  
604 -- Unhook the functions
605 if( Original_CanSendAuctionQuery ) then
606 CanSendAuctionQuery = Original_CanSendAuctionQuery;
607 Original_CanSendAuctionQuery = nil;
608 end
609 if( Original_AuctionFrameBrowse_OnEvent ) then
610 AuctionFrameBrowse_OnEvent = Original_AuctionFrameBrowse_OnEvent;
611 Original_AuctionFrameBrowse_OnEvent = nil;
612 end
613 if( Original_AuctionFrameBrowse_Update ) then
614 AuctionFrameBrowse_Update = Original_AuctionFrameBrowse_Update;
615 Original_AuctionFrameBrowse_Update = nil;
616 end
617  
618 -- Update the Browse UI.
619 BrowseNoResultsText:Hide();
620 BrowseNoResultsText:SetText("");
621 AuctionFrameBrowse_Update();
622 end
623 end
624  
625 -------------------------------------------------------------------------------
626 -- Attempt to process the request queue. Based on the current state, this
627 -- method performs the next action needed to process the queue.
628 -------------------------------------------------------------------------------
629 function processRequestQueue()
630 -- Check if we should toss the results of the last query. Sometimes
631 -- Blizzard never updates all the owner information. We give it 20
632 -- seconds, then give up and try again.
633 if (CurrentSearchParams.queryResponse == true and
634 CurrentSearchParams.queryComplete == false and
635 CurrentSearchParams.queryTime and
636 time() - CurrentSearchParams.queryTime >= 20) then
637 -- Discard the results of the search and try again.
638 CurrentSearchParams.name = nil;
639 CurrentSearchParams.minLevel = nil;
640 CurrentSearchParams.maxLevel = nil;
641 CurrentSearchParams.invTypeIndex = nil;
642 CurrentSearchParams.classIndex = nil;
643 CurrentSearchParams.subclassIndex = nil;
644 CurrentSearchParams.page = nil;
645 CurrentSearchParams.isUsable = nil;
646 CurrentSearchParams.qualityIndex = nil;
647 CurrentSearchParams.queryTime = nil;
648 CurrentSearchParams.queryResponse = true;
649 CurrentSearchParams.queryComplete = true;
650 CurrentSearchParams.targetCountForPage = nil;
651 Auctioneer.Util.ChatPrint(string.format(_AUCT('AuctionScanRedo'), 20));
652 end
653  
654 -- Process the bid queue!
655 if (beginProcessingRequestQueue()) then
656 while (table.getn(RequestQueue) > 0 and not isQueryInProgress() and not isBidInProgress()) do
657 local request = RequestQueue[1];
658 --debugPrint("Processing bid queue: "..request.name..", "..request.count..", "..nilSafe(request.owner)..", "..nilSafe(request.bid)..", "..nilSafe(request.buyout));
659 --debugPrint("CurrentSearchParams: ");
660 --debugPrint(" name: "..nilSafe(CurrentSearchParams.name));
661 --debugPrint(" minLevel: "..nilSafe(CurrentSearchParams.minLevel));
662 --debugPrint(" maxLevel: "..nilSafe(CurrentSearchParams.maxLevel));
663  
664 if (CurrentSearchParams.name and
665 CurrentSearchParams.name == request.name and
666 CurrentSearchParams.minLevel == "" and
667 CurrentSearchParams.maxLevel == "" and
668 CurrentSearchParams.invTypeIndex == nil and
669 CurrentSearchParams.classIndex == nil and
670 CurrentSearchParams.page == request.currentPage and
671 CurrentSearchParams.isUsable == nil and
672 CurrentSearchParams.qualityIndex == nil) then
673 processPage();
674  
675 elseif (canSendAuctionQuery()) then
676 QueryAuctionItems(request.name, "", "", nil, nil, nil, request.currentPage, nil, nil);
677  
678 else
679 -- We gotta wait to be able to send a query.
680 break;
681  
682 end
683 end
684  
685 -- If we've emptied the RequestQueue, then end the processing
686 if (table.getn(RequestQueue) == 0) then
687 endProcessingRequestQueue();
688 end
689 end
690 end
691  
692 -------------------------------------------------------------------------------
693 -- Searches the current page for an auction matching the first request in
694 -- the request queue. If it finds the auction, it carries out the specified
695 -- action (bid/buyout).
696 -------------------------------------------------------------------------------
697 function processPage()
698 local request = RequestQueue[1];
699  
700 -- Iterate through each item on the page, searching for a match
701 local lastIndexOnPage, totalAuctions = GetNumAuctionItems("list");
702 debugPrint("Processing page "..request.currentPage.." starting at index "..request.currentIndex.." ("..lastIndexOnPage.." on page; "..totalAuctions.." in total)");
703 debugPrint("Searching for item: "..request.id..", "..request.rprop..", "..request.enchant..", "..request.name..", "..request.count..", "..request.min..", "..request.buyout..", "..request.unique..", "..request.bid);
704  
705 local foundMatchingAuction = false;
706 for indexOnPage = request.currentIndex, lastIndexOnPage do
707 -- Check if this item matches
708 local name, texture, count, quality, canUse, level, minBid, minIncrement, buyoutPrice, bidAmount, highBidder, owner = GetAuctionItemInfo("list", indexOnPage);
709 local link = GetAuctionItemLink("list", indexOnPage);
710 local id, rprop, enchant, unique = EnhTooltip.BreakLink(link);
711 debugPrint("Processing item "..indexOnPage..": "..id..", "..rprop..", "..enchant..", "..name..", "..count..", "..minBid..", "..buyoutPrice..", "..unique..", "..bidAmount);
712  
713 if ((request.id == id) and
714 (request.rprop == rprop) and
715 (request.enchant == enchant) and
716 (request.name == name) and
717 (request.count == count) and
718 (request.min == minBid) and
719 (request.buyout == buyoutPrice) and
720 (request.unique == unique)) then
721  
722 local bid = nil;
723  
724 -- Check if the auction is owned by the player.
725 if (isPlayerOnAccount(owner)) then
726 table.insert(request.results, BidResultCodes["OwnAuction"]);
727 local output = string.format(_AUCT('FrmtSkippedBiddingOnOwnAuction'), request.name, request.count);
728 chatPrint(output);
729  
730 -- Check for a buyout request
731 elseif (request.buyout == request.bid) then
732 bid = request.buyout;
733  
734 -- Otherwise it must be a bid request
735 else
736 -- Check if we are already the high bidder
737 if (highBidder) then
738 table.insert(request.results, BidResultCodes["AlreadyHighBidder"]);
739 local output = string.format(_AUCT('FrmtAlreadyHighBidder'), request.name, request.count);
740 chatPrint(output);
741  
742 -- Check if the item has been bid on
743 elseif (bidAmount ~= 0) then
744 -- Check the bid matches what we are looking for
745 if (bidAmount == request.bid) then
746 bid = bidAmount + minIncrement;
747  
748 -- Check if there is already a higher bidder
749 elseif (bidAmount > request.bid) then
750 table.insert(request.results, BidResultCodes["AlreadyHigherBid"]);
751 local output = string.format(_AUCT('FrmtSkippedAuctionWithHigherBid'), request.name, request.count);
752 chatPrint(output);
753  
754 -- Otherwise the bid must be lower...
755 else
756 table.insert(request.results, BidResultCodes["CurrentBidLower"]);
757 local output = string.format(_AUCT('FrmtSkippedAuctionWithLowerBid'), request.name, request.count);
758 chatPrint(output);
759 end
760  
761 -- Otherwise the item hasn't been bid on
762 else
763 -- Check the bid matches what we are looking for
764 if (minBid == request.bid) then
765 bid = minBid;
766  
767 -- Otherwise the min bid is lower...
768 else
769 table.insert(request.results, BidResultCodes["CurrentBidLower"]);
770 local output = string.format(_AUCT('FrmtSkippedAuctionWithLowerBid'), request.name, request.count);
771 chatPrint(output);
772 end
773 end
774 end
775  
776 -- If we've settled on a bid, do it now!
777 if (bid) then
778 foundMatchingAuction = true;
779  
780 -- Check if we've reached the bid limit on this request.
781 if (request.bidCount == request.maxBids) then
782 -- Report that the maximum number of bids has been reached.
783 local output = string.format(_AUCT('FrmtMaxBidsReached'), request.name, request.count, request.maxBids);
784 chatPrint(output);
785 debugPrint("Reached max bids!");
786  
787 -- Add the bid result to the request.
788 table.insert(request.results, BidResultCodes["MaxBidsReached"]);
789  
790 -- Since this request didn't fully completed due to bid
791 -- limits, update the currentIndex and save it as the
792 -- last request. If the next request is for the same item,
793 -- it will pickup where this request left off.
794 LastRequest = request;
795 request.currentIndex = indexOnPage;
796 removeRequestFromQueue();
797  
798 else
799 -- Successful bid/buyouts result in the query results being
800 -- updated. To prevent additional queries from being sent
801 -- until the list is updated, we flip the complete flag
802 -- back to false. If the bid fails we'll manually flip
803 -- the flag back to true again.
804 CurrentSearchParams.queryTime = time();
805 CurrentSearchParams.queryResponse = false;
806 CurrentSearchParams.queryComplete = false;
807 if (bid == buyoutPrice) then
808 CurrentSearchParams.targetCountForPage = lastIndexOnPage - 1;
809 end
810  
811 -- Update the starting point for this page
812 request.currentIndex = indexOnPage;
813 request.bidAttempts = request.bidAttempts + 1;
814  
815 -- Place the bid! This MUST be done last since the response
816 -- can be received during the call to PlaceAuctionBid.
817 debugPrint("Placing bid on "..name.. " at "..bid.." (index "..indexOnPage..")");
818 PlaceAuctionBid("list", indexOnPage, bid, request);
819  
820 end
821  
822 break;
823 end
824 end
825 end
826  
827 -- If an item was not found to bid on...
828 if (not foundMatchingAuction) then
829 -- When an item is bought out on the page, the item is not replaced
830 -- with an item from a subsequent page. Nor is the item removed from
831 -- the total count. Thus if there were 7 items total before the buyout,
832 -- GetNumAuctionItems() will report 6 items on the page and but still
833 -- 7 total after the buyout.
834 if (lastIndexOnPage == 0 or
835 request.currentPage * NUM_AUCTION_ITEMS_PER_PAGE + lastIndexOnPage == totalAuctions) then
836 -- Reached the end of the line for this item, remove it from the queue
837 request.currentIndex = lastIndexOnPage + 1;
838 removeRequestFromQueue();
839  
840 else
841 -- Continue looking for items on the next page.
842 request.currentPage = request.currentPage + 1;
843 request.currentIndex = 1;
844 end
845 end
846 end
847  
848 -------------------------------------------------------------------------------
849 -- Adds a bid request to the queue. For bids, the bid parameter should be the
850 -- current bid (or minimum bid in the case the item isn't bid on). For buyouts,
851 -- the bid parameter should be the buyout price.
852 -------------------------------------------------------------------------------
853 function bidAuction(bid, signature, maxBids, callbackFunc, callbackParam)
854 debugPrint("BidAuction("..bid..", "..signature..")");
855 local id,rprop,enchant,name,count,min,buyout,unique = Auctioneer.Core.GetItemSignature(signature);
856 if (bid and id and rprop and enchant and name and count and min and buyout and unique) then
857 -- Make sure we have a valid maxBids
858 if (maxBids == nil or maxBids < 1) then
859 maxBids = 25;
860 end
861  
862 -- Create a bid request.
863 local request = {};
864 request.id = id;
865 request.rprop = rprop;
866 request.enchant = enchant;
867 request.name = name;
868 request.count = count;
869 request.min = min;
870 request.buyout = buyout;
871 request.unique = unique;
872 request.bid = bid;
873 request.maxBids = maxBids;
874 request.callback = { func = callbackFunc, param = callbackParam };
875  
876 -- Queue the bid request and kick off request processing!
877 addRequestToQueue(request);
878 processRequestQueue();
879 end
880 end
881  
882 -------------------------------------------------------------------------------
883 -- Dumps the state of the BidManager to the chat window.
884 -------------------------------------------------------------------------------
885 function dumpState()
886 chatPrint("BidManager State:");
887 chatPrint(" IsBidInProgress: "..boolString(isBidInProgress()));
888 chatPrint(" IsQueryInProgress: "..boolString(isQueryInProgress()));
889 chatPrint(" RequestQueue ("..table.getn(RequestQueue).."):");
890 chatPrint(" PendingBids ("..table.getn(PendingBids).."):");
891 chatPrint(" CurrentSearchParams:");
892 chatPrint(" name: "..nilSafe(CurrentSearchParams.name));
893 chatPrint(" minLevel: "..nilSafe(CurrentSearchParams.minLevel));
894 chatPrint(" maxLevel: "..nilSafe(CurrentSearchParams.maxLevel));
895 chatPrint(" invTypeIndex: "..nilSafe(CurrentSearchParams.invTypeIndex));
896 chatPrint(" classIndex: "..nilSafe(CurrentSearchParams.classIndex));
897 chatPrint(" subclassIndex: "..nilSafe(CurrentSearchParams.subclassIndex));
898 chatPrint(" page: "..nilSafe(CurrentSearchParams.page));
899 chatPrint(" isUsable: "..boolString(CurrentSearchParams.isUsable));
900 chatPrint(" qualityIndex: "..nilSafe(CurrentSearchParams.qualityIndex));
901 chatPrint(" queryResponse: "..boolString(CurrentSearchParams.queryResponse));
902 chatPrint(" queryComplete: "..boolString(CurrentSearchParams.queryComplete));
903 chatPrint(" targetCountForPage: "..nilSafe(CurrentSearchParams.targetCountForPage));
904 end
905  
906 -------------------------------------------------------------------------------
907 -------------------------------------------------------------------------------
908 function nilSafe(string)
909 if (string) then
910 return string;
911 end
912 return "<nil>";
913 end
914  
915 -------------------------------------------------------------------------------
916 -------------------------------------------------------------------------------
917 function boolString(value)
918 if (value) then
919 return "true";
920 end
921 return "false";
922 end
923  
924 -------------------------------------------------------------------------------
925 -------------------------------------------------------------------------------
926 chatPrint = Auctioneer.Util.ChatPrint;
927  
928 -------------------------------------------------------------------------------
929 -------------------------------------------------------------------------------
930 debugPrint = EnhTooltip.DebugPrint;
931  
932 -------------------------------------------------------------------------------
933 -- Public API
934 -------------------------------------------------------------------------------
935 AucBidManager =
936 {
937 -- Exported functions
938 BidAuction = bidAuction;
939 IsProcessingRequest = isProcessingRequest;
940 GetRequestCount = getRequestCount;
941 DumpState = dumpState;
942 };