diff --git a/src/AuctionHouseBot.cpp b/src/AuctionHouseBot.cpp index 948234a..60a03bb 100644 --- a/src/AuctionHouseBot.cpp +++ b/src/AuctionHouseBot.cpp @@ -1587,20 +1587,100 @@ void AuctionHouseBot::InitializeConfiguration() void AuctionHouseBot::EmptyAuctionHouses() { vector configs = { AllianceConfig, HordeConfig, NeutralConfig }; + vector ahBotActiveAuctions; + + // Get all auctions owned by AHBots which have no bidders + std::string queryString = "SELECT id FROM auctionhouse WHERE itemowner IN ({}) AND buyguid = 0"; + QueryResult result = CharacterDatabase.Query(queryString, AHCharactersGUIDsForQuery); + auto trans = CharacterDatabase.BeginTransaction(); - - for (FactionSpecificAuctionHouseConfig config : configs) { - AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(config.GetAHFID()); - auto auctionEntryMap = auctionHouse->GetAuctions(); - for (auto itr = auctionEntryMap.begin(); itr != auctionEntryMap.end();) + if (result && result->GetRowCount() > 0) + { + do { - AuctionEntry* auction = itr->second; + uint32 tmpdata = result->Fetch()->Get(); + ahBotActiveAuctions.push_back(tmpdata); + } while (result->NextRow()); - auction->DeleteFromDB(trans); - sAuctionMgr->RemoveAItem(auction->item_guid); - auctionHouse->RemoveAuction(auction); + // Remove bidder-less AHBot items from the AHs + for (FactionSpecificAuctionHouseConfig config : configs) { + AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(config.GetAHFID()); + for (uint32 auctionID : ahBotActiveAuctions) + { + vector::iterator iter = ahBotActiveAuctions.begin(); + AuctionEntry* auction = auctionHouse->GetAuction(*iter); + ahBotActiveAuctions.erase(iter); - itr = auctionEntryMap.erase(itr); + auction->DeleteFromDB(trans); + sAuctionMgr->RemoveAItem(auction->item_guid); + auctionHouse->RemoveAuction(auction); + } + } + } + + // Get auctions owned by AHBots which DO have a bidder, return their deposits + std::vector> auctionsToRefund; + std::string refundQueryString = "SELECT id, buyguid FROM auctionhouse WHERE itemowner IN ({}) AND buyguid != 0"; + QueryResult refundResult = CharacterDatabase.Query(refundQueryString, AHCharactersGUIDsForQuery); + if (refundResult && refundResult->GetRowCount() > 0) + { + do + { + Field* fields = refundResult->Fetch(); + uint32 auctionID = fields[0].Get(); + uint32 buyGUID = fields[1].Get(); + auctionsToRefund.push_back({auctionID, buyGUID}); + } while (refundResult->NextRow()); + + // Remove AHBot items with bidders from the AHs + for (FactionSpecificAuctionHouseConfig config : configs) { + AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(config.GetAHFID()); + for (std::pair p : auctionsToRefund) + { + uint32 auctionID = p.first; + uint32 buyGUID = p.second; + + // Lookup accountID and accountName associated with bidder character + std::string accountIDQueryString = "SELECT account FROM characters WHERE guid = {}"; + std::string accountNameQueryString = "SELECT username FROM acore_auth.account WHERE id = {}"; + QueryResult accountIDQueryResult = CharacterDatabase.Query(accountIDQueryString, buyGUID); + + if (!accountIDQueryResult) + continue; + + uint32 bidderAccountID = accountIDQueryResult->Fetch()->Get(); + QueryResult accountNameQueryResult = LoginDatabase.Query(accountNameQueryString, bidderAccountID); + + if (!accountNameQueryResult) + continue; + + std::string bidderAccountName = accountNameQueryResult->Fetch()->Get(); + + // Load Player information, and issue refund + auto session = std::make_unique( + bidderAccountID, std::move(bidderAccountName), 0, nullptr, + SEC_PLAYER, sWorld->getIntConfig(CONFIG_EXPANSION), 0, LOCALE_enUS, 0, false, false, 0 + ); + auto player = std::make_unique(session.get()); + if (!player) + continue; + player->Initialize(buyGUID); + + auto iter = auctionsToRefund.begin(); + AuctionEntry* auction = auctionHouse->GetAuction(iter->first); + if (!auction) + continue; + + uint32 auctionCut = auction->GetAuctionCut(); + sAuctionMgr->SendAuctionCancelledToBidderMail(auction, trans); + player->ModifyMoney(-int32(auctionCut)); // ModifyMoney() already handles negative check + + // Remove item from the AH + auctionsToRefund.erase(iter); + auction->DeleteFromDB(trans); + sAuctionMgr->RemoveAItem(auction->item_guid); + auctionHouse->RemoveAuction(auction); + } } }