TrinityCore
AuctionHouseHandler.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "WorldSession.h"
19#include "AccountMgr.h"
20#include "AuctionHouseMgr.h"
21#include "AuctionHousePackets.h"
22#include "CharacterCache.h"
23#include "Creature.h"
24#include "DatabaseEnv.h"
25#include "GameTime.h"
26#include "Item.h"
27#include "Language.h"
28#include "Log.h"
29#include "ObjectAccessor.h"
30#include "ObjectMgr.h"
31#include "Player.h"
32#include "Util.h"
33#include "World.h"
34#include <sstream>
35
37{
38 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, browseQuery.TaintedBy.has_value());
39 if (throttle.Throttled)
40 return;
41
43 if (!creature)
44 {
45 TC_LOG_DEBUG("network", "WORLD: HandleAuctionListItems - {} not found or you can't interact with him.", browseQuery.Auctioneer.ToString());
46 return;
47 }
48
49 // remove fake death
50 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
52
53 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
54
55 TC_LOG_DEBUG("auctionHouse", "Auctionhouse search {}, searchedname: {}, levelmin: {}, levelmax: {}, filters: {}",
56 browseQuery.Auctioneer.ToString(), browseQuery.Name, browseQuery.MinLevel, browseQuery.MaxLevel, AsUnderlyingType(browseQuery.Filters));
57
58 std::wstring name;
59 if (!Utf8toWStr(browseQuery.Name, name))
60 return;
61
63
65 if (!browseQuery.ItemClassFilters.empty())
66 {
67 classFilters.emplace();
68
69 for (auto const& classFilter : browseQuery.ItemClassFilters)
70 {
71 if (!classFilter.SubClassFilters.empty())
72 {
73 for (auto const& subClassFilter : classFilter.SubClassFilters)
74 {
75 if (classFilter.ItemClass < MAX_ITEM_CLASS)
76 {
77 classFilters->Classes[classFilter.ItemClass].SubclassMask |= 1 << subClassFilter.ItemSubclass;
78 if (subClassFilter.ItemSubclass < MAX_ITEM_SUBCLASS_TOTAL)
79 classFilters->Classes[classFilter.ItemClass].InvTypes[subClassFilter.ItemSubclass] = subClassFilter.InvTypeMask;
80 }
81 }
82 }
83 else
84 classFilters->Classes[classFilter.ItemClass].SubclassMask = AuctionSearchClassFilters::FILTER_SKIP_SUBCLASS;
85 }
86 }
87
88 auctionHouse->BuildListBuckets(listBucketsResult, _player,
89 name, browseQuery.MinLevel, browseQuery.MaxLevel, browseQuery.Filters, classFilters,
90 browseQuery.KnownPets, browseQuery.MaxPetLevel, browseQuery.Offset, browseQuery.Sorts);
91
93 listBucketsResult.DesiredDelay = uint32(throttle.DelayUntilNext.count());
94 SendPacket(listBucketsResult.Write());
95}
96
98{
99 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, cancelCommoditiesPurchase.TaintedBy.has_value(), AuctionCommand::PlaceBid);
100 if (throttle.Throttled)
101 return;
102
104 if (!creature)
105 {
106 TC_LOG_DEBUG("network", "WORLD: HandleAuctionCancelCommoditiesPurchase - {} not found or you can't interact with him.",
107 cancelCommoditiesPurchase.Auctioneer.ToString());
108 return;
109 }
110
111 // remove fake death
112 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
114
115 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
116 auctionHouse->CancelCommodityQuote(_player->GetGUID());
117}
118
120{
121 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, confirmCommoditiesPurchase.TaintedBy.has_value(), AuctionCommand::PlaceBid);
122 if (throttle.Throttled)
123 return;
124
126 if (!creature)
127 {
128 TC_LOG_DEBUG("network", "WORLD: HandleAuctionConfirmCommoditiesPurchase - {} not found or you can't interact with him.", confirmCommoditiesPurchase.Auctioneer.ToString());
129 return;
130 }
131
132 // remove fake death
133 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
135
136 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
137
138 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
139 if (auctionHouse->BuyCommodity(trans, _player, confirmCommoditiesPurchase.ItemID, confirmCommoditiesPurchase.Quantity, throttle.DelayUntilNext))
140 {
141 AddTransactionCallback(CharacterDatabase.AsyncCommitTransaction(trans)).AfterComplete([this, buyerGuid = _player->GetGUID(), throttle](bool success)
142 {
143 if (GetPlayer() && GetPlayer()->GetGUID() == buyerGuid)
144 {
145 if (success)
146 {
147 GetPlayer()->UpdateCriteria(CriteriaType::AuctionsWon, 1);
148 SendAuctionCommandResult(0, AuctionCommand::PlaceBid, AuctionResult::Ok, throttle.DelayUntilNext);
149 }
150 else
151 SendAuctionCommandResult(0, AuctionCommand::PlaceBid, AuctionResult::CommodityPurchaseFailed, throttle.DelayUntilNext);
152 }
153 });
154 }
155}
156
158{
159 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, getCommodityQuote.TaintedBy.has_value(), AuctionCommand::PlaceBid);
160 if (throttle.Throttled)
161 return;
162
164 if (!creature)
165 {
166 TC_LOG_DEBUG("network", "WORLD: HandleAuctionStartCommoditiesPurchase - {} not found or you can't interact with him.",
167 getCommodityQuote.Auctioneer.ToString());
168 return;
169 }
170
171 // remove fake death
172 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
174
175 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
176
178
179 if (CommodityQuote const* quote = auctionHouse->CreateCommodityQuote(_player, getCommodityQuote.ItemID, getCommodityQuote.Quantity))
180 {
181 commodityQuoteResult.TotalPrice = quote->TotalPrice;
182 commodityQuoteResult.Quantity = quote->Quantity;
183 commodityQuoteResult.QuoteDuration = std::chrono::duration_cast<Milliseconds>(quote->ValidTo - GameTime::Now());
184 }
185
186 commodityQuoteResult.ItemID = getCommodityQuote.ItemID;
187 commodityQuoteResult.DesiredDelay = uint32(throttle.DelayUntilNext.count());
188
189 SendPacket(commodityQuoteResult.Write());
190}
191
193{
195 if (!unit)
196 {
197 TC_LOG_DEBUG("network", "WORLD: HandleAuctionHelloOpcode - Unit ({}) not found or you can't interact with him.", hello.Guid.ToString());
198 return;
199 }
200
201 // remove fake death
202 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
204
205 SendAuctionHello(hello.Guid, unit);
206}
207
209{
210 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, listBiddedItems.TaintedBy.has_value());
211 if (throttle.Throttled)
212 return;
213
215 if (!creature)
216 {
217 TC_LOG_DEBUG("network", "WORLD: HandleAuctionListBidderItems - {} not found or you can't interact with him.", listBiddedItems.Auctioneer.ToString());
218 return;
219 }
220
221 // remove fake death
222 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
224
225 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
226
228
229 Player* player = GetPlayer();
230 auctionHouse->BuildListBiddedItems(result, player, listBiddedItems.Offset, listBiddedItems.Sorts);
231 result.DesiredDelay = uint32(throttle.DelayUntilNext.count());
232 SendPacket(result.Write());
233}
234
236{
237 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, listBucketsByBucketKeys.TaintedBy.has_value());
238 if (throttle.Throttled)
239 return;
240
242 if (!creature)
243 {
244 TC_LOG_DEBUG("network", "WORLD: HandleAuctionListBucketsByBucketKeys - {} not found or you can't interact with him.",
245 listBucketsByBucketKeys.Auctioneer.ToString());
246 return;
247 }
248
249 // remove fake death
250 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
252
253 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
254
256
257 auctionHouse->BuildListBuckets(listBucketsResult, _player, listBucketsByBucketKeys.BucketKeys, listBucketsByBucketKeys.Sorts);
258
260 listBucketsResult.DesiredDelay = uint32(throttle.DelayUntilNext.count());
261 SendPacket(listBucketsResult.Write());
262}
263
265{
266 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, listItemsByBucketKey.TaintedBy.has_value());
267 if (throttle.Throttled)
268 return;
269
271 if (!creature)
272 {
273 TC_LOG_DEBUG("network", "WORLD: HandleAuctionListItemsByBucketKey - {} not found or you can't interact with him.", listItemsByBucketKey.Auctioneer.ToString());
274 return;
275 }
276
277 // remove fake death
278 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
280
281 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
282
284 listItemsResult.DesiredDelay = uint32(throttle.DelayUntilNext.count());
285 listItemsResult.BucketKey = listItemsByBucketKey.BucketKey;
286 ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(listItemsByBucketKey.BucketKey.ItemID);
287 listItemsResult.ListType = itemTemplate && itemTemplate->GetMaxStackSize() > 1 ? AuctionHouseListType::Commodities : AuctionHouseListType::Items;
288
289 auctionHouse->BuildListAuctionItems(listItemsResult, _player, listItemsByBucketKey.BucketKey, listItemsByBucketKey.Offset, listItemsByBucketKey.Sorts);
290
291 SendPacket(listItemsResult.Write());
292}
293
295{
296 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, listItemsByItemID.TaintedBy.has_value());
297 if (throttle.Throttled)
298 return;
299
301 if (!creature)
302 {
303 TC_LOG_DEBUG("network", "WORLD: HandleAuctionListItemsByItemID - {} not found or you can't interact with him.", listItemsByItemID.Auctioneer.ToString());
304 return;
305 }
306
307 // remove fake death
308 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
310
311 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
312
314 listItemsResult.DesiredDelay = uint32(throttle.DelayUntilNext.count());
315 listItemsResult.BucketKey.ItemID = listItemsByItemID.ItemID;
316 ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(listItemsByItemID.ItemID);
317 listItemsResult.ListType = itemTemplate && itemTemplate->GetMaxStackSize() > 1 ? AuctionHouseListType::Commodities : AuctionHouseListType::Items;
318
319 auctionHouse->BuildListAuctionItems(listItemsResult, _player, listItemsByItemID.ItemID, listItemsByItemID.Offset, listItemsByItemID.Sorts);
320
321 SendPacket(listItemsResult.Write());
322}
323
324//this void sends player info about his auctions
326{
327 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, listOwnedItems.TaintedBy.has_value());
328 if (throttle.Throttled)
329 return;
330
332 if (!creature)
333 {
334 TC_LOG_DEBUG("network", "WORLD: HandleAuctionListOwnerItems - {} not found or you can't interact with him.", listOwnedItems.Auctioneer.ToString());
335 return;
336 }
337
338 // remove fake death
339 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
341
342 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
343
345
346 auctionHouse->BuildListOwnedItems(result, _player, listOwnedItems.Offset, listOwnedItems.Sorts);
347 result.DesiredDelay = uint32(throttle.DelayUntilNext.count());
348 SendPacket(result.Write());
349}
350
351// this function is called when client bids or buys out auction
353{
354 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, placeBid.TaintedBy.has_value(), AuctionCommand::PlaceBid);
355 if (throttle.Throttled)
356 return;
357
359 if (!creature)
360 {
361 TC_LOG_DEBUG("network", "WORLD: HandleAuctionPlaceBid - {} not found or you can't interact with him.", placeBid.Auctioneer.ToString());
362 return;
363 }
364
365 // auction house does not deal with copper
366 if (placeBid.BidAmount % SILVER)
367 {
369 return;
370 }
371
372 // remove fake death
373 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
375
376 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
377
378 AuctionPosting* auction = auctionHouse->GetAuction(placeBid.AuctionID);
379 if (!auction || auction->IsCommodity())
380 {
382 return;
383 }
384
385 Player* player = GetPlayer();
386
387 // check auction owner - cannot buy own auctions
388 if (auction->Owner == player->GetGUID() || auction->OwnerAccount == GetAccountGUID())
389 {
391 return;
392 }
393
394 bool canBid = auction->MinBid != 0;
395 bool canBuyout = auction->BuyoutOrUnitPrice != 0;
396
397 // buyout attempt with wrong amount
398 if (!canBid && placeBid.BidAmount != auction->BuyoutOrUnitPrice)
399 {
401 return;
402 }
403
404 uint64 minBid = auction->BidAmount ? auction->BidAmount + auction->CalculateMinIncrement() : auction->MinBid;
405 if (canBid && placeBid.BidAmount < minBid)
406 {
408 return;
409 }
410
411 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
412
413 uint64 priceToPay = placeBid.BidAmount;
414 if (!auction->Bidder.IsEmpty())
415 {
416 // return money to previous bidder
417 if (auction->Bidder != player->GetGUID())
418 auctionHouse->SendAuctionOutbid(auction, player->GetGUID(), placeBid.BidAmount, trans);
419 else
420 priceToPay = placeBid.BidAmount - auction->BidAmount;
421 }
422
423 // check money
424 if (!player->HasEnoughMoney(priceToPay))
425 {
427 return;
428 }
429
430 player->ModifyMoney(-int64(priceToPay));
431 auction->Bidder = player->GetGUID();
432 auction->BidAmount = placeBid.BidAmount;
435 else
437
438 if (canBuyout && placeBid.BidAmount == auction->BuyoutOrUnitPrice)
439 {
440 // buyout
441 auctionHouse->SendAuctionSold(auction, nullptr, trans);
442 auctionHouse->SendAuctionWon(auction, player, trans);
443
444 auctionHouse->RemoveAuction(trans, auction);
445 }
446 else
447 {
448 // place bid
450 stmt->setUInt64(0, auction->Bidder.GetCounter());
451 stmt->setUInt64(1, auction->BidAmount);
452 stmt->setUInt8(2, auction->ServerFlags.AsUnderlyingType());
453 stmt->setUInt32(3, auction->Id);
454 trans->Append(stmt);
455
456 if (auction->BidderHistory.insert(player->GetGUID()).second)
457 {
458 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_AUCTION_BIDDER);
459 stmt->setUInt32(0, auction->Id);
460 stmt->setUInt64(1, player->GetGUID().GetCounter());
461 trans->Append(stmt);
462 }
463
464 // Not sure if we must send this now.
465 if (Player* owner = ObjectAccessor::FindConnectedPlayer(auction->Owner))
466 owner->GetSession()->SendAuctionOwnerBidNotification(auction);
467 }
468
469 player->SaveInventoryAndGoldToDB(trans);
470 AddTransactionCallback(CharacterDatabase.AsyncCommitTransaction(trans)).AfterComplete(
471 [this, auctionId = placeBid.AuctionID, bidAmount = placeBid.BidAmount, auctionPlayerGuid = _player->GetGUID(), throttle](bool success)
472 {
473 if (GetPlayer() && GetPlayer()->GetGUID() == auctionPlayerGuid)
474 {
475 if (success)
476 {
477 GetPlayer()->UpdateCriteria(CriteriaType::HighestAuctionBid, bidAmount);
478 SendAuctionCommandResult(auctionId, AuctionCommand::PlaceBid, AuctionResult::Ok, throttle.DelayUntilNext);
479 }
480 else
481 SendAuctionCommandResult(auctionId, AuctionCommand::PlaceBid, AuctionResult::DatabaseError, throttle.DelayUntilNext);
482 }
483 });
484}
485
487{
488 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, removeItem.TaintedBy.has_value(), AuctionCommand::Cancel);
489 if (throttle.Throttled)
490 return;
491
493 if (!creature)
494 {
495 TC_LOG_DEBUG("network", "WORLD: HandleAuctionRemoveItem - {} not found or you can't interact with him.", removeItem.Auctioneer.ToString());
496 return;
497 }
498
499 // remove fake death
500 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
502
503 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
504
505 AuctionPosting* auction = auctionHouse->GetAuction(removeItem.AuctionID);
506 Player* player = GetPlayer();
507
508 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
509 if (auction && auction->Owner == player->GetGUID())
510 {
511 if (auction->Bidder.IsEmpty()) // If we have a bidder, we have to send him the money he paid
512 {
513 uint64 cancelCost = CalculatePct(auction->BidAmount, 5u);
514 if (!player->HasEnoughMoney(cancelCost)) //player doesn't have enough money
515 {
517 return;
518 }
519 auctionHouse->SendAuctionCancelledToBidder(auction, trans);
520 player->ModifyMoney(-int64(cancelCost));
521 }
522
523 auctionHouse->SendAuctionRemoved(auction, player, trans);
524 }
525 else
526 {
528 //this code isn't possible ... maybe there should be assert
529 TC_LOG_ERROR("entities.player.cheat", "CHEATER : {} tried to cancel auction (id: {}) of another player or auction is NULL", player->GetGUID().ToString(), removeItem.AuctionID);
530 return;
531 }
532
533 // client bug - instead of removing auction in the UI, it only substracts 1 from visible count
534 uint32 auctionIdForClient = auction->IsCommodity() ? 0 : auction->Id;
535
536 // Now remove the auction
537 player->SaveInventoryAndGoldToDB(trans);
538 auctionHouse->RemoveAuction(trans, auction);
539 AddTransactionCallback(CharacterDatabase.AsyncCommitTransaction(trans)).AfterComplete(
540 [this, auctionIdForClient, auctionPlayerGuid = _player->GetGUID(), throttle](bool success)
541 {
542 if (GetPlayer() && GetPlayer()->GetGUID() == auctionPlayerGuid)
543 {
544 if (success)
545 SendAuctionCommandResult(auctionIdForClient, AuctionCommand::Cancel, AuctionResult::Ok, throttle.DelayUntilNext); //inform player, that auction is removed
546 else
547 SendAuctionCommandResult(0, AuctionCommand::Cancel, AuctionResult::DatabaseError, throttle.DelayUntilNext);
548 }
549 });
550}
551
553{
555 if (!creature)
556 {
557 TC_LOG_DEBUG("network", "WORLD: HandleReplicateItems - {} not found or you can't interact with him.", replicateItems.Auctioneer.ToString());
558 return;
559 }
560
561 // remove fake death
562 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
564
565 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
566
568
569 auctionHouse->BuildReplicate(response, GetPlayer(),
570 replicateItems.ChangeNumberGlobal, replicateItems.ChangeNumberCursor, replicateItems.ChangeNumberTombstone, replicateItems.Count);
571
572 response.DesiredDelay = sWorld->getIntConfig(CONFIG_AUCTION_SEARCH_DELAY) * 5;
573 response.Result = 0;
574 SendPacket(response.Write());
575}
576
578{
580 stmt->setUInt64(0, _player->GetGUID().GetCounter());
581 GetQueryProcessor().AddCallback(CharacterDatabase.AsyncQuery(stmt)).WithPreparedCallback([this](PreparedQueryResult favoriteAuctionResult)
582 {
584 if (favoriteAuctionResult)
585 {
586 favoriteItems.Items.reserve(favoriteAuctionResult->GetRowCount());
587
588 do
589 {
590 Field* fields = favoriteAuctionResult->Fetch();
591
592 WorldPackets::AuctionHouse::AuctionFavoriteInfo& item = favoriteItems.Items.emplace_back();
593 item.Order = fields[0].GetUInt32();
594 item.ItemID = fields[1].GetUInt32();
595 item.ItemLevel = fields[2].GetUInt32();
596 item.BattlePetSpeciesID = fields[3].GetUInt32();
597 item.SuffixItemNameDescriptionID = fields[4].GetUInt32();
598
599 } while (favoriteAuctionResult->NextRow());
600
601 }
602 SendPacket(favoriteItems.Write());
603 });
604}
605
607{
608 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, sellCommodity.TaintedBy.has_value(), AuctionCommand::SellItem);
609 if (throttle.Throttled)
610 return;
611
612 if (!sellCommodity.UnitPrice || sellCommodity.UnitPrice > MAX_MONEY_AMOUNT)
613 {
614 TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Player {} {} attempted to sell item with invalid price.", _player->GetName(), _player->GetGUID().ToString());
616 return;
617 }
618
619 // auction house does not deal with copper
620 if (sellCommodity.UnitPrice % SILVER)
621 {
623 return;
624 }
625
627 if (!creature)
628 {
629 TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Unit {} not found or you can't interact with him.", sellCommodity.Auctioneer.ToString());
630 return;
631 }
632
633 uint32 houseId = 0;
634 AuctionHouseEntry const* auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntry(creature->GetFaction(), &houseId);
635 if (!auctionHouseEntry)
636 {
637 TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Unit {} has wrong faction.", sellCommodity.Auctioneer.ToString());
638 return;
639 }
640
641 switch (sellCommodity.RunTime)
642 {
643 case 1 * MIN_AUCTION_TIME / MINUTE:
644 case 2 * MIN_AUCTION_TIME / MINUTE:
645 case 4 * MIN_AUCTION_TIME / MINUTE:
646 break;
647 default:
649 return;
650 }
651
652 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
654
655 // find all items for sale
656 uint64 totalCount = 0;
657 std::unordered_map<ObjectGuid, std::pair<Item*, uint64>> items2;
658
659 for (WorldPackets::AuctionHouse::AuctionItemForSale const& itemForSale : sellCommodity.Items)
660 {
661 Item* item = _player->GetItemByGuid(itemForSale.Guid);
662 if (!item)
663 {
665 return;
666 }
667
668 if (item->GetTemplate()->GetMaxStackSize() == 1)
669 {
670 // not commodity, must use different packet
672 return;
673 }
674
675 // verify that all items belong to the same bucket
676 if (!items2.empty() && AuctionsBucketKey::ForItem(item) != AuctionsBucketKey::ForItem(items2.begin()->second.first))
677 {
679 return;
680 }
681
682 if (sAuctionMgr->GetAItem(item->GetGUID()) || !item->CanBeTraded() || item->IsNotEmptyBag() ||
683 item->GetTemplate()->HasFlag(ITEM_FLAG_CONJURED) || *item->m_itemData->Expiration ||
684 item->GetCount() < itemForSale.UseCount)
685 {
687 return;
688 }
689
690 std::pair<Item*, uint64>& soldItem = items2[item->GetGUID()];
691 soldItem.first = item;
692 soldItem.second += itemForSale.UseCount;
693 if (item->GetCount() < soldItem.second)
694 {
695 // check that we have enough of this item to sell
697 return;
698 }
699
700 totalCount += itemForSale.UseCount;
701 }
702
703 if (!totalCount)
704 {
706 return;
707 }
708
709 Seconds auctionTime = Seconds(int64(std::chrono::duration_cast<Seconds>(Minutes(sellCommodity.RunTime)).count() * double(sWorld->getRate(RATE_AUCTION_TIME))));
710 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
711
712 uint64 deposit = AuctionHouseMgr::GetCommodityAuctionDeposit(items2.begin()->second.first->GetTemplate(), Minutes(sellCommodity.RunTime), totalCount);
713 if (!_player->HasEnoughMoney(deposit))
714 {
716 return;
717 }
718
719 uint32 auctionId = sObjectMgr->GenerateAuctionID();
720 AuctionPosting auction;
721 auction.Id = auctionId;
722 auction.Owner = _player->GetGUID();
723 auction.OwnerAccount = GetAccountGUID();
724 auction.BuyoutOrUnitPrice = sellCommodity.UnitPrice;
725 auction.Deposit = deposit;
727 auction.EndTime = auction.StartTime + auctionTime;
728
729 // keep track of what was cloned to undo/modify counts later
730 std::unordered_map<Item* /*original*/, std::unique_ptr<Item> /*clone*/> clones;
731 for (std::pair<ObjectGuid const, std::pair<Item*, uint64>>& it : items2)
732 {
733 Item* itemForSale;
734 if (it.second.first->GetCount() != it.second.second)
735 {
736 itemForSale = it.second.first->CloneItem(it.second.second, _player);
737 if (!itemForSale)
738 {
739 TC_LOG_ERROR("network", "CMSG_AUCTION_SELL_COMMODITY: Could not create clone of item {}", it.second.first->GetEntry());
741 return;
742 }
743
744 clones.emplace(it.second.first, itemForSale);
745 }
746 }
747
748 if (!sAuctionMgr->PendingAuctionAdd(_player, auctionHouse->GetAuctionHouseId(), auction.Id, auction.Deposit))
749 {
751 return;
752 }
753
754 TC_LOG_INFO("network", "CMSG_AUCTION_SELL_COMMODITY: {} {} is selling item {} {} to auctioneer {} with count {} with with unit price {} and with time {} (in sec) in auctionhouse {}",
755 _player->GetGUID().ToString(), _player->GetName(), items2.begin()->second.first->GetNameForLocaleIdx(sWorld->GetDefaultDbcLocale()),
756 ([&items2]()
757 {
758 std::stringstream ss;
759 auto itr = items2.begin();
760 ss << (itr++)->first.ToString();
761 for (; itr != items2.end(); ++itr)
762 ss << ',' << itr->first.ToString();
763 return ss.str();
764 }()).c_str(),
765 creature->GetGUID().ToString().c_str(), totalCount, sellCommodity.UnitPrice, uint32(auctionTime.count()), auctionHouse->GetAuctionHouseId());
766
768 {
769 Item* logItem = items2.begin()->second.first;
770 sLog->OutCommand(GetAccountId(), "GM {} (Account: {}) create auction: {} (Entry: {} Count: {})",
771 GetPlayerName(), GetAccountId(), logItem->GetNameForLocaleIdx(sWorld->GetDefaultDbcLocale()), logItem->GetEntry(), totalCount);
772 }
773
774 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
775
776 for (std::pair<ObjectGuid const, std::pair<Item*, uint64>> const& it : items2)
777 {
778 Item* itemForSale = it.second.first;
779 auto cloneItr = clones.find(it.second.first);
780 if (cloneItr != clones.end())
781 {
782 Item* original = itemForSale;
783 original->SetCount(original->GetCount() - uint32(it.second.second));
784 original->SetState(ITEM_CHANGED, _player);
785 _player->ItemRemovedQuestCheck(original->GetEntry(), uint32(it.second.second));
786 original->SaveToDB(trans);
787
788 itemForSale = cloneItr->second.release();
789 }
790 else
791 {
792 _player->MoveItemFromInventory(itemForSale->GetBagSlot(), itemForSale->GetSlot(), true);
793 itemForSale->DeleteFromInventoryDB(trans);
794 }
795
796 itemForSale->SaveToDB(trans);
797 auction.Items.push_back(itemForSale);
798 }
799
800 auctionHouse->AddAuction(trans, std::move(auction));
802
803 AddTransactionCallback(CharacterDatabase.AsyncCommitTransaction(trans)).AfterComplete([this, auctionId, auctionPlayerGuid = _player->GetGUID(), throttle](bool success)
804 {
805 if (GetPlayer() && GetPlayer()->GetGUID() == auctionPlayerGuid)
806 {
807 if (success)
808 {
809 GetPlayer()->UpdateCriteria(CriteriaType::ItemsPostedAtAuction, 1);
810 SendAuctionCommandResult(auctionId, AuctionCommand::SellItem, AuctionResult::Ok, throttle.DelayUntilNext);
811 }
812 else
813 SendAuctionCommandResult(0, AuctionCommand::SellItem, AuctionResult::DatabaseError, throttle.DelayUntilNext);
814 }
815 });
816}
817
819{
820 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, sellItem.TaintedBy.has_value(), AuctionCommand::SellItem);
821 if (throttle.Throttled)
822 return;
823
824 if (sellItem.Items.size() != 1 || sellItem.Items[0].UseCount != 1)
825 {
827 return;
828 }
829
830 if (!sellItem.MinBid && !sellItem.BuyoutPrice)
831 {
833 return;
834 }
835
836 if (sellItem.MinBid > MAX_MONEY_AMOUNT || sellItem.BuyoutPrice > MAX_MONEY_AMOUNT)
837 {
838 TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Player {} {} attempted to sell item with higher price than max gold amount.", _player->GetName(), _player->GetGUID().ToString());
840 return;
841 }
842
843 // auction house does not deal with copper
844 if (sellItem.MinBid % SILVER || sellItem.BuyoutPrice % SILVER)
845 {
847 return;
848 }
849
851 if (!creature)
852 {
853 TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Unit {} not found or you can't interact with him.", sellItem.Auctioneer.ToString());
854 return;
855 }
856
857 uint32 houseId = 0;
858 AuctionHouseEntry const* auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntry(creature->GetFaction(), &houseId);
859 if (!auctionHouseEntry)
860 {
861 TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Unit {} has wrong faction.", sellItem.Auctioneer.ToString());
862 return;
863 }
864
865 switch (sellItem.RunTime)
866 {
867 case 1 * MIN_AUCTION_TIME / MINUTE:
868 case 2 * MIN_AUCTION_TIME / MINUTE:
869 case 4 * MIN_AUCTION_TIME / MINUTE:
870 break;
871 default:
873 return;
874 }
875
876 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
878
879 Item* item = _player->GetItemByGuid(sellItem.Items[0].Guid);
880 if (!item)
881 {
883 return;
884 }
885
886 if (item->GetTemplate()->GetMaxStackSize() > 1)
887 {
888 // commodity, must use different packet
890 return;
891 }
892
893 if (sAuctionMgr->GetAItem(item->GetGUID()) || !item->CanBeTraded() || item->IsNotEmptyBag() ||
894 item->GetTemplate()->HasFlag(ITEM_FLAG_CONJURED) || *item->m_itemData->Expiration ||
895 item->GetCount() != 1)
896 {
898 return;
899 }
900
901 Seconds auctionTime = Seconds(int64(std::chrono::duration_cast<Seconds>(Minutes(sellItem.RunTime)).count() * double(sWorld->getRate(RATE_AUCTION_TIME))));
902 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
903
905 if (!_player->HasEnoughMoney(deposit))
906 {
908 return;
909 }
910
911 uint32 auctionId = sObjectMgr->GenerateAuctionID();
912
913 AuctionPosting auction;
914 auction.Id = auctionId;
915 auction.Owner = _player->GetGUID();
916 auction.OwnerAccount = GetAccountGUID();
917 auction.MinBid = sellItem.MinBid;
918 auction.BuyoutOrUnitPrice = sellItem.BuyoutPrice;
919 auction.Deposit = deposit;
920 auction.BidAmount = sellItem.MinBid;
922 auction.EndTime = auction.StartTime + auctionTime;
923
925 {
926 sLog->OutCommand(GetAccountId(), "GM {} (Account: {}) create auction: {} (Entry: {} Count: {})",
928 }
929
930 auction.Items.push_back(item);
931
932 TC_LOG_INFO("network", "CMSG_AuctionAction::SellItem: {} {} is selling item {} {} to auctioneer {} with count {} with initial bid {} with buyout {} and with time {} (in sec) in auctionhouse {}",
934 creature->GetGUID().ToString(), item->GetCount(), sellItem.MinBid, sellItem.BuyoutPrice, uint32(auctionTime.count()), auctionHouse->GetAuctionHouseId());
935
936 // Add to pending auctions, or fail with insufficient funds error
937 if (!sAuctionMgr->PendingAuctionAdd(_player, auctionHouse->GetAuctionHouseId(), auctionId, auction.Deposit))
938 {
940 return;
941 }
942
943 _player->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true);
944
945 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
946 item->DeleteFromInventoryDB(trans);
947 item->SaveToDB(trans);
948
949 auctionHouse->AddAuction(trans, std::move(auction));
951 AddTransactionCallback(CharacterDatabase.AsyncCommitTransaction(trans)).AfterComplete([this, auctionId, auctionPlayerGuid = _player->GetGUID(), throttle](bool success)
952 {
953 if (GetPlayer() && GetPlayer()->GetGUID() == auctionPlayerGuid)
954 {
955 if (success)
956 {
957 GetPlayer()->UpdateCriteria(CriteriaType::ItemsPostedAtAuction, 1);
958 SendAuctionCommandResult(auctionId, AuctionCommand::SellItem, AuctionResult::Ok, throttle.DelayUntilNext);
959 }
960 else
961 SendAuctionCommandResult(0, AuctionCommand::SellItem, AuctionResult::DatabaseError, throttle.DelayUntilNext);
962 }
963 });
964}
965
967{
968 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, false);
969 if (throttle.Throttled)
970 return;
971
972 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
973
975 stmt->setUInt64(0, _player->GetGUID().GetCounter());
976 stmt->setUInt32(1, setFavoriteItem.Item.Order);
977 trans->Append(stmt);
978
979 if (!setFavoriteItem.IsNotFavorite)
980 {
981 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_FAVORITE_AUCTION);
982 stmt->setUInt64(0, _player->GetGUID().GetCounter());
983 stmt->setUInt32(1, setFavoriteItem.Item.Order);
984 stmt->setUInt32(2, setFavoriteItem.Item.ItemID);
985 stmt->setUInt32(3, setFavoriteItem.Item.ItemLevel);
986 stmt->setUInt32(4, setFavoriteItem.Item.BattlePetSpeciesID);
987 stmt->setUInt32(5, setFavoriteItem.Item.SuffixItemNameDescriptionID);
988 trans->Append(stmt);
989 }
990
991 CharacterDatabase.CommitTransaction(trans);
992}
993
994//this void causes that auction window is opened
996{
997 if (GetPlayer()->GetLevel() < sWorld->getIntConfig(CONFIG_AUCTION_LEVEL_REQ))
998 {
1000 return;
1001 }
1002
1003 AuctionHouseEntry const* ahEntry = AuctionHouseMgr::GetAuctionHouseEntry(unit->GetFaction(), nullptr);
1004 if (!ahEntry)
1005 return;
1006
1008 auctionHelloResponse.Guid = guid;
1009 auctionHelloResponse.OpenForBusiness = true; // 3.3.3: 1 - AH enabled, 0 - AH disabled
1010 SendPacket(auctionHelloResponse.Write());
1011}
1012
1013void WorldSession::SendAuctionCommandResult(uint32 auctionId, AuctionCommand command, AuctionResult errorCode, Milliseconds delayForNextAction, InventoryResult bagError /*= 0*/)
1014{
1016 auctionCommandResult.AuctionID = auctionId;
1017 auctionCommandResult.Command = AsUnderlyingType(command);
1018 auctionCommandResult.ErrorCode = AsUnderlyingType(errorCode);
1019 auctionCommandResult.BagResult = AsUnderlyingType(bagError);
1020 auctionCommandResult.DesiredDelay = uint32(delayForNextAction.count());
1021 SendPacket(auctionCommandResult.Write());
1022}
1023
1024void WorldSession::SendAuctionClosedNotification(AuctionPosting const* auction, float mailDelay, bool sold)
1025{
1027 packet.Info.Initialize(auction);
1028 packet.ProceedsMailDelay = mailDelay;
1029 packet.Sold = sold;
1030 SendPacket(packet.Write());
1031}
1032
1034{
1036 packet.Info.Initialize(auction);
1037 packet.Bidder = auction->Bidder;
1038 packet.MinIncrement = auction->CalculateMinIncrement();
1039 SendPacket(packet.Write());
1040}
uint32 constexpr MIN_AUCTION_TIME
AuctionResult
#define sAuctionMgr
AuctionPostingServerFlag
AuctionCommand
@ CHAR_DEL_CHARACTER_FAVORITE_AUCTION
@ CHAR_SEL_CHARACTER_FAVORITE_AUCTIONS
@ CHAR_INS_AUCTION_BIDDER
@ CHAR_UPD_AUCTION_BID
@ CHAR_INS_CHARACTER_FAVORITE_AUCTION
@ MINUTE
Definition: Common.h:29
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
int64_t int64
Definition: Define.h:137
uint64_t uint64
Definition: Define.h:141
uint32_t uint32
Definition: Define.h:142
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition: Duration.h:32
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition: Duration.h:29
std::chrono::minutes Minutes
Minutes shorthand typedef.
Definition: Duration.h:35
InventoryResult
Definition: ItemDefines.h:25
@ EQUIP_ERR_TOO_MUCH_GOLD
Definition: ItemDefines.h:104
#define MAX_ITEM_SUBCLASS_TOTAL
Definition: ItemTemplate.h:760
@ ITEM_FLAG_CONJURED
Definition: ItemTemplate.h:177
#define MAX_ITEM_CLASS
Definition: ItemTemplate.h:442
@ ITEM_CHANGED
Definition: Item.h:55
@ LANG_AUCTION_REQ
Definition: Language.h:1161
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
#define sLog
Definition: Log.h:130
#define TC_LOG_INFO(filterType__,...)
Definition: Log.h:159
#define sObjectMgr
Definition: ObjectMgr.h:1946
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
uint64 const MAX_MONEY_AMOUNT
Definition: Player.cpp:158
@ SILVER
@ SPELL_AURA_FEIGN_DEATH
@ UNIT_NPC_FLAG_AUCTIONEER
Definition: UnitDefines.h:318
@ UNIT_NPC_FLAG_2_NONE
Definition: UnitDefines.h:336
@ UNIT_STATE_DIED
Definition: Unit.h:255
bool Utf8toWStr(char const *utf8str, size_t csize, wchar_t *wstr, size_t &wsize)
Definition: Util.cpp:383
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition: Util.h:491
T CalculatePct(T base, U pct)
Definition: Util.h:72
static uint64 GetItemAuctionDeposit(Player const *player, Item const *item, Minutes time)
static uint64 GetCommodityAuctionDeposit(ItemTemplate const *item, Minutes time, uint32 quantity)
static AuctionHouseEntry const * GetAuctionHouseEntry(uint32 factionTemplateId, uint32 *houseId)
void SendAuctionWon(AuctionPosting const *auction, Player *bidder, CharacterDatabaseTransaction trans) const
AuctionPosting * GetAuction(uint32 auctionId)
void AddAuction(CharacterDatabaseTransaction trans, AuctionPosting auction)
void BuildListBiddedItems(WorldPackets::AuctionHouse::AuctionListBiddedItemsResult &listBiddedItemsResult, Player const *player, uint32 offset, std::span< WorldPackets::AuctionHouse::AuctionSortDef const > sorts) const
void SendAuctionRemoved(AuctionPosting const *auction, Player *owner, CharacterDatabaseTransaction trans) const
void SendAuctionSold(AuctionPosting const *auction, Player *owner, CharacterDatabaseTransaction trans) const
void BuildListOwnedItems(WorldPackets::AuctionHouse::AuctionListOwnedItemsResult &listOwnedItemsResult, Player const *player, uint32 offset, std::span< WorldPackets::AuctionHouse::AuctionSortDef const > sorts) const
uint32 GetAuctionHouseId() const
void BuildListBuckets(WorldPackets::AuctionHouse::AuctionListBucketsResult &listBucketsResult, Player const *player, std::wstring const &name, uint8 minLevel, uint8 maxLevel, EnumFlag< AuctionHouseFilterMask > filters, Optional< AuctionSearchClassFilters > const &classFilters, std::span< uint8 const > knownPetBits, uint8 maxKnownPetLevel, uint32 offset, std::span< WorldPackets::AuctionHouse::AuctionSortDef const > sorts) const
void BuildReplicate(WorldPackets::AuctionHouse::AuctionReplicateResponse &replicateResponse, Player *player, uint32 global, uint32 cursor, uint32 tombstone, uint32 count)
void SendAuctionCancelledToBidder(AuctionPosting const *auction, CharacterDatabaseTransaction trans) const
void BuildListAuctionItems(WorldPackets::AuctionHouse::AuctionListItemsResult &listItemsResult, Player const *player, AuctionsBucketKey const &bucketKey, uint32 offset, std::span< WorldPackets::AuctionHouse::AuctionSortDef const > sorts) const
void CancelCommodityQuote(ObjectGuid guid)
CommodityQuote const * CreateCommodityQuote(Player const *player, uint32 itemId, uint32 quantity)
bool BuyCommodity(CharacterDatabaseTransaction trans, Player *player, uint32 itemId, uint32 quantity, Milliseconds delayForNextAction)
void RemoveAuction(CharacterDatabaseTransaction trans, AuctionPosting *auction, std::map< uint32, AuctionPosting >::iterator *auctionItr=nullptr)
void SendAuctionOutbid(AuctionPosting const *auction, ObjectGuid newBidder, uint64 newBidAmount, CharacterDatabaseTransaction trans) const
constexpr std::underlying_type_t< T > AsUnderlyingType() const
Definition: EnumFlag.h:122
Definition: Item.h:170
static void DeleteFromInventoryDB(CharacterDatabaseTransaction trans, ObjectGuid::LowType itemGuid)
Definition: Item.cpp:1129
void SetState(ItemUpdateState state, Player *forplayer=nullptr)
Definition: Item.cpp:1166
uint8 GetSlot() const
Definition: Item.h:280
virtual void SaveToDB(CharacterDatabaseTransaction trans)
Definition: Item.cpp:561
Item * CloneItem(uint32 count, Player const *player=nullptr) const
Definition: Item.cpp:1655
bool CanBeTraded(bool mail=false, bool trade=false) const
Definition: Item.cpp:1250
void SetCount(uint32 value)
Definition: Item.cpp:1275
ItemTemplate const * GetTemplate() const
Definition: Item.cpp:1141
std::string GetNameForLocaleIdx(LocaleConstant locale) const override
Definition: Item.cpp:524
bool IsNotEmptyBag() const
Definition: Item.cpp:535
uint32 GetCount() const
Definition: Item.h:273
uint8 GetBagSlot() const
Definition: Item.cpp:1239
UF::UpdateField< UF::ItemData, 0, TYPEID_ITEM > m_itemData
Definition: Item.h:449
LowType GetCounter() const
Definition: ObjectGuid.h:293
bool IsEmpty() const
Definition: ObjectGuid.h:319
std::string ToString() const
Definition: ObjectGuid.cpp:554
uint32 GetEntry() const
Definition: Object.h:161
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
void ItemRemovedQuestCheck(uint32 entry, uint32 count)
Definition: Player.cpp:16645
bool ModifyMoney(int64 amount, bool sendError=true)
Definition: Player.cpp:24098
Creature * GetNPCIfCanInteractWith(ObjectGuid const &guid, NPCFlags npcFlags, NPCFlags2 npcFlags2) const
Definition: Player.cpp:1947
void SaveInventoryAndGoldToDB(CharacterDatabaseTransaction trans)
Definition: Player.cpp:20364
void MoveItemFromInventory(uint8 bag, uint8 slot, bool update)
Definition: Player.cpp:12134
Item * GetItemByGuid(ObjectGuid guid) const
Definition: Player.cpp:9566
bool HasEnoughMoney(uint64 amount) const
Definition: Player.h:1740
void setUInt8(const uint8 index, const uint8 value)
void setUInt32(const uint8 index, const uint32 value)
void setUInt64(const uint8 index, const uint64 value)
QueryCallback && WithPreparedCallback(std::function< void(PreparedQueryResult)> &&callback)
void AfterComplete(std::function< void(bool)> callback) &
Definition: Transaction.h:108
void RemoveAurasByType(AuraType auraType, std::function< bool(AuraApplication const *)> const &check, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3812
uint32 GetFaction() const override
Definition: Unit.h:858
std::string const & GetName() const
Definition: Object.h:555
Array< AuctionListFilterClass, 7 > ItemClassFilters
int32 BagResult
the bid error. Possible values are AuctionError
int32 ErrorCode
the error code that was generated when trying to perform the action. Possible values are AuctionError
int32 AuctionID
the id of the auction that triggered this notification
int32 Command
the type of action that triggered this notification. Possible values are AuctionAction
void SendAuctionHello(ObjectGuid guid, Creature *unit)
void HandleAuctionConfirmCommoditiesPurchase(WorldPackets::AuctionHouse::AuctionConfirmCommoditiesPurchase &confirmCommoditiesPurchase)
void SendAuctionClosedNotification(AuctionPosting const *auction, float mailDelay, bool sold)
void HandleAuctionListItemsByBucketKey(WorldPackets::AuctionHouse::AuctionListItemsByBucketKey &listItemsByBucketKey)
char const * GetTrinityString(uint32 entry) const
void SendNotification(char const *format,...) ATTR_PRINTF(2
void HandleAuctionRemoveItem(WorldPackets::AuctionHouse::AuctionRemoveItem &removeItem)
void HandleAuctionSetFavoriteItem(WorldPackets::AuctionHouse::AuctionSetFavoriteItem &setFavoriteItem)
void HandleAuctionSellItem(WorldPackets::AuctionHouse::AuctionSellItem &sellItem)
ObjectGuid GetAccountGUID() const
void HandleAuctionReplicateItems(WorldPackets::AuctionHouse::AuctionReplicateItems &replicateItems)
void HandleAuctionCancelCommoditiesPurchase(WorldPackets::AuctionHouse::AuctionCancelCommoditiesPurchase &cancelCommoditiesPurchase)
Player * GetPlayer() const
void HandleAuctionListBiddedItems(WorldPackets::AuctionHouse::AuctionListBiddedItems &listBiddedItems)
void HandleAuctionPlaceBid(WorldPackets::AuctionHouse::AuctionPlaceBid &placeBid)
void HandleAuctionListItemsByItemID(WorldPackets::AuctionHouse::AuctionListItemsByItemID &listItemsByItemID)
QueryCallbackProcessor & GetQueryProcessor()
TransactionCallback & AddTransactionCallback(TransactionCallback &&callback)
bool HasPermission(uint32 permissionId)
void HandleAuctionSellCommodity(WorldPackets::AuctionHouse::AuctionSellCommodity &sellCommodity)
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
uint32 GetAccountId() const
void HandleAuctionBrowseQuery(WorldPackets::AuctionHouse::AuctionBrowseQuery &browseQuery)
Player * _player
void HandleAuctionGetCommodityQuote(WorldPackets::AuctionHouse::AuctionGetCommodityQuote &startCommoditiesPurchase)
void HandleAuctionRequestFavoriteList(WorldPackets::AuctionHouse::AuctionRequestFavoriteList &requestFavoriteList)
void HandleAuctionHelloOpcode(WorldPackets::AuctionHouse::AuctionHelloRequest &hello)
void HandleAuctionListBucketsByBucketKeys(WorldPackets::AuctionHouse::AuctionListBucketsByBucketKeys &listBucketsByBucketKeys)
void SendAuctionOwnerBidNotification(AuctionPosting const *auction)
std::string const & GetPlayerName() const
void HandleAuctionListOwnedItems(WorldPackets::AuctionHouse::AuctionListOwnedItems &listOwnedItems)
void SendAuctionCommandResult(uint32 auctionId, AuctionCommand command, AuctionResult errorCode, Milliseconds delayForNextAction, InventoryResult bagError=InventoryResult(0))
Notifies the client of the result of his last auction operation. It is called when the player bids,...
#define sWorld
Definition: World.h:931
@ CONFIG_AUCTION_LEVEL_REQ
Definition: World.h:328
@ CONFIG_AUCTION_SEARCH_DELAY
Definition: World.h:426
@ RATE_AUCTION_TIME
Definition: World.h:519
SystemTimePoint GetSystemTime()
Current chrono system_clock time point.
Definition: GameTime.cpp:54
TimePoint Now()
Current chrono steady_clock time point.
Definition: GameTime.cpp:59
TC_GAME_API Player * FindConnectedPlayer(ObjectGuid const &)
@ RBAC_PERM_LOG_GM_TRADE
Definition: RBAC.h:64
bool IsCommodity() const
ObjectGuid Bidder
std::vector< Item * > Items
ObjectGuid Owner
static uint64 CalculateMinIncrement(uint64 bidAmount)
EnumFlag< AuctionPostingServerFlag > ServerFlags
ObjectGuid OwnerAccount
uint64 BuyoutOrUnitPrice
SystemTimePoint StartTime
GuidUnorderedSet BidderHistory
SystemTimePoint EndTime
Milliseconds DelayUntilNext
static AuctionsBucketKey ForItem(Item const *item)
uint32 GetMaxStackSize() const
Definition: ItemTemplate.h:847
bool HasFlag(ItemFlags flag) const
Definition: ItemTemplate.h:871
char const * GetDefaultLocaleName() const