TrinityCore
Loading...
Searching...
No Matches
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 "GossipDef.h"
27#include "Item.h"
28#include "Language.h"
29#include "Log.h"
30#include "ObjectAccessor.h"
31#include "ObjectMgr.h"
32#include "Player.h"
33#include "Util.h"
34#include "World.h"
35#include <sstream>
36
38{
39 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, browseQuery.TaintedBy.has_value());
40 if (throttle.Throttled)
41 return;
42
44 if (!creature)
45 {
46 TC_LOG_DEBUG("network", "WORLD: HandleAuctionListItems - {} not found or you can't interact with him.", browseQuery.Auctioneer.ToString());
47 return;
48 }
49
50 // remove fake death
51 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
53
54 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
55
56 TC_LOG_DEBUG("auctionHouse", "Auctionhouse search {}, searchedname: {}, levelmin: {}, levelmax: {}, filters: {}",
57 browseQuery.Auctioneer.ToString(), browseQuery.Name, browseQuery.MinLevel, browseQuery.MaxLevel, AsUnderlyingType(browseQuery.Filters));
58
59 std::wstring name;
60 if (!Utf8toWStr(browseQuery.Name, name))
61 return;
62
64
66 if (!browseQuery.ItemClassFilters.empty())
67 {
68 classFilters.emplace();
69
70 for (auto const& classFilter : browseQuery.ItemClassFilters)
71 {
72 if (!classFilter.SubClassFilters.empty())
73 {
74 for (auto const& subClassFilter : classFilter.SubClassFilters)
75 {
76 if (classFilter.ItemClass < MAX_ITEM_CLASS)
77 {
78 classFilters->Classes[classFilter.ItemClass].SubclassMask |= 1 << subClassFilter.ItemSubclass;
79 if (subClassFilter.ItemSubclass < MAX_ITEM_SUBCLASS_TOTAL)
80 classFilters->Classes[classFilter.ItemClass].InvTypes[subClassFilter.ItemSubclass] = subClassFilter.InvTypeMask;
81 }
82 }
83 }
84 else
85 classFilters->Classes[classFilter.ItemClass].SubclassMask = AuctionSearchClassFilters::FILTER_SKIP_SUBCLASS;
86 }
87 }
88
89 auctionHouse->BuildListBuckets(listBucketsResult, _player,
90 name, browseQuery.MinLevel, browseQuery.MaxLevel, browseQuery.Filters, classFilters,
91 browseQuery.KnownPets, browseQuery.MaxPetLevel, browseQuery.Offset, browseQuery.Sorts);
92
94 listBucketsResult.DesiredDelay = uint32(throttle.DelayUntilNext.count());
95 SendPacket(listBucketsResult.Write());
96}
97
99{
100 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, cancelCommoditiesPurchase.TaintedBy.has_value(), AuctionCommand::PlaceBid);
101 if (throttle.Throttled)
102 return;
103
105 if (!creature)
106 {
107 TC_LOG_DEBUG("network", "WORLD: HandleAuctionCancelCommoditiesPurchase - {} not found or you can't interact with him.",
108 cancelCommoditiesPurchase.Auctioneer.ToString());
109 return;
110 }
111
112 // remove fake death
113 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
115
116 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
117 auctionHouse->CancelCommodityQuote(_player->GetGUID());
118}
119
121{
122 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, confirmCommoditiesPurchase.TaintedBy.has_value(), AuctionCommand::PlaceBid);
123 if (throttle.Throttled)
124 return;
125
127 if (!creature)
128 {
129 TC_LOG_DEBUG("network", "WORLD: HandleAuctionConfirmCommoditiesPurchase - {} not found or you can't interact with him.", confirmCommoditiesPurchase.Auctioneer.ToString());
130 return;
131 }
132
133 // remove fake death
134 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
136
137 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
138
139 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
140 if (auctionHouse->BuyCommodity(trans, _player, confirmCommoditiesPurchase.ItemID, confirmCommoditiesPurchase.Quantity, throttle.DelayUntilNext))
141 {
142 AddTransactionCallback(CharacterDatabase.AsyncCommitTransaction(trans)).AfterComplete([this, buyerGuid = _player->GetGUID(), throttle](bool success)
143 {
144 if (GetPlayer() && GetPlayer()->GetGUID() == buyerGuid)
145 {
146 if (success)
147 {
148 GetPlayer()->UpdateCriteria(CriteriaType::AuctionsWon, 1);
149 SendAuctionCommandResult(0, AuctionCommand::PlaceBid, AuctionResult::Ok, throttle.DelayUntilNext);
150 }
151 else
152 SendAuctionCommandResult(0, AuctionCommand::PlaceBid, AuctionResult::CommodityPurchaseFailed, throttle.DelayUntilNext);
153 }
154 });
155 }
156}
157
159{
160 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, getCommodityQuote.TaintedBy.has_value(), AuctionCommand::PlaceBid);
161 if (throttle.Throttled)
162 return;
163
165 if (!creature)
166 {
167 TC_LOG_DEBUG("network", "WORLD: HandleAuctionStartCommoditiesPurchase - {} not found or you can't interact with him.",
168 getCommodityQuote.Auctioneer.ToString());
169 return;
170 }
171
172 // remove fake death
173 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
175
176 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
177
179
180 if (CommodityQuote const* quote = auctionHouse->CreateCommodityQuote(_player, getCommodityQuote.ItemID, getCommodityQuote.Quantity))
181 {
182 commodityQuoteResult.TotalPrice = quote->TotalPrice;
183 commodityQuoteResult.Quantity = quote->Quantity;
184 commodityQuoteResult.QuoteDuration = std::chrono::duration_cast<Milliseconds>(quote->ValidTo - GameTime::Now());
185 }
186
187 commodityQuoteResult.ItemID = getCommodityQuote.ItemID;
188 commodityQuoteResult.DesiredDelay = uint32(throttle.DelayUntilNext.count());
189
190 SendPacket(commodityQuoteResult.Write());
191}
192
194{
196 if (!unit)
197 {
198 TC_LOG_DEBUG("network", "WORLD: HandleAuctionHelloOpcode - Unit ({}) not found or you can't interact with him.", hello.Guid.ToString());
199 return;
200 }
201
202 // remove fake death
203 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
205
206 SendAuctionHello(hello.Guid, unit);
207}
208
210{
211 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, listBiddedItems.TaintedBy.has_value());
212 if (throttle.Throttled)
213 return;
214
216 if (!creature)
217 {
218 TC_LOG_DEBUG("network", "WORLD: HandleAuctionListBidderItems - {} not found or you can't interact with him.", listBiddedItems.Auctioneer.ToString());
219 return;
220 }
221
222 // remove fake death
223 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
225
226 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
227
229
230 Player* player = GetPlayer();
231 auctionHouse->BuildListBiddedItems(result, player, listBiddedItems.Offset, listBiddedItems.Sorts);
232 result.DesiredDelay = uint32(throttle.DelayUntilNext.count());
233 SendPacket(result.Write());
234}
235
237{
238 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, listBucketsByBucketKeys.TaintedBy.has_value());
239 if (throttle.Throttled)
240 return;
241
243 if (!creature)
244 {
245 TC_LOG_DEBUG("network", "WORLD: HandleAuctionListBucketsByBucketKeys - {} not found or you can't interact with him.",
246 listBucketsByBucketKeys.Auctioneer.ToString());
247 return;
248 }
249
250 // remove fake death
251 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
253
254 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
255
257
258 auctionHouse->BuildListBuckets(listBucketsResult, _player, listBucketsByBucketKeys.BucketKeys, listBucketsByBucketKeys.Sorts);
259
261 listBucketsResult.DesiredDelay = uint32(throttle.DelayUntilNext.count());
262 SendPacket(listBucketsResult.Write());
263}
264
266{
267 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, listItemsByBucketKey.TaintedBy.has_value());
268 if (throttle.Throttled)
269 return;
270
272 if (!creature)
273 {
274 TC_LOG_DEBUG("network", "WORLD: HandleAuctionListItemsByBucketKey - {} not found or you can't interact with him.", listItemsByBucketKey.Auctioneer.ToString());
275 return;
276 }
277
278 // remove fake death
279 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
281
282 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
283
285 listItemsResult.DesiredDelay = uint32(throttle.DelayUntilNext.count());
286 listItemsResult.BucketKey = listItemsByBucketKey.BucketKey;
287 ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(listItemsByBucketKey.BucketKey.ItemID);
288 listItemsResult.ListType = itemTemplate && itemTemplate->GetMaxStackSize() > 1 ? AuctionHouseListType::Commodities : AuctionHouseListType::Items;
289
290 auctionHouse->BuildListAuctionItems(listItemsResult, _player, listItemsByBucketKey.BucketKey, listItemsByBucketKey.Offset, listItemsByBucketKey.Sorts);
291
292 SendPacket(listItemsResult.Write());
293}
294
296{
297 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, listItemsByItemID.TaintedBy.has_value());
298 if (throttle.Throttled)
299 return;
300
302 if (!creature)
303 {
304 TC_LOG_DEBUG("network", "WORLD: HandleAuctionListItemsByItemID - {} not found or you can't interact with him.", listItemsByItemID.Auctioneer.ToString());
305 return;
306 }
307
308 // remove fake death
309 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
311
312 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
313
315 listItemsResult.DesiredDelay = uint32(throttle.DelayUntilNext.count());
316 listItemsResult.BucketKey.ItemID = listItemsByItemID.ItemID;
317 ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(listItemsByItemID.ItemID);
318 listItemsResult.ListType = itemTemplate && itemTemplate->GetMaxStackSize() > 1 ? AuctionHouseListType::Commodities : AuctionHouseListType::Items;
319
320 auctionHouse->BuildListAuctionItems(listItemsResult, _player, listItemsByItemID.ItemID, listItemsByItemID.Offset, listItemsByItemID.Sorts);
321
322 SendPacket(listItemsResult.Write());
323}
324
325//this void sends player info about his auctions
327{
328 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, listOwnedItems.TaintedBy.has_value());
329 if (throttle.Throttled)
330 return;
331
333 if (!creature)
334 {
335 TC_LOG_DEBUG("network", "WORLD: HandleAuctionListOwnerItems - {} not found or you can't interact with him.", listOwnedItems.Auctioneer.ToString());
336 return;
337 }
338
339 // remove fake death
340 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
342
343 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
344
346
347 auctionHouse->BuildListOwnedItems(result, _player, listOwnedItems.Offset, listOwnedItems.Sorts);
348 result.DesiredDelay = uint32(throttle.DelayUntilNext.count());
349 SendPacket(result.Write());
350}
351
352// this function is called when client bids or buys out auction
354{
355 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, placeBid.TaintedBy.has_value(), AuctionCommand::PlaceBid);
356 if (throttle.Throttled)
357 return;
358
360 if (!creature)
361 {
362 TC_LOG_DEBUG("network", "WORLD: HandleAuctionPlaceBid - {} not found or you can't interact with him.", placeBid.Auctioneer.ToString());
363 return;
364 }
365
366 // auction house does not deal with copper
367 if (placeBid.BidAmount % SILVER)
368 {
370 return;
371 }
372
373 // remove fake death
374 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
376
377 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
378
379 AuctionPosting* auction = auctionHouse->GetAuction(placeBid.AuctionID);
380 if (!auction || auction->IsCommodity())
381 {
383 return;
384 }
385
386 Player* player = GetPlayer();
387
388 // check auction owner - cannot buy own auctions
389 if (auction->Owner == player->GetGUID() || auction->OwnerAccount == GetAccountGUID())
390 {
392 return;
393 }
394
395 bool canBid = auction->MinBid != 0;
396 bool canBuyout = auction->BuyoutOrUnitPrice != 0;
397
398 // buyout attempt with wrong amount
399 if (!canBid && placeBid.BidAmount != auction->BuyoutOrUnitPrice)
400 {
402 return;
403 }
404
405 uint64 minBid = auction->BidAmount ? auction->BidAmount + auction->CalculateMinIncrement() : auction->MinBid;
406 if (canBid && placeBid.BidAmount < minBid)
407 {
409 return;
410 }
411
412 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
413
414 uint64 priceToPay = placeBid.BidAmount;
415 if (!auction->Bidder.IsEmpty())
416 {
417 // return money to previous bidder
418 if (auction->Bidder != player->GetGUID())
419 auctionHouse->SendAuctionOutbid(auction, player->GetGUID(), placeBid.BidAmount, trans);
420 else
421 priceToPay = placeBid.BidAmount - auction->BidAmount;
422 }
423
424 // check money
425 if (!player->HasEnoughMoney(priceToPay))
426 {
428 return;
429 }
430
431 player->ModifyMoney(-int64(priceToPay));
432 auction->Bidder = player->GetGUID();
433 auction->BidAmount = placeBid.BidAmount;
436 else
438
439 if (canBuyout && placeBid.BidAmount == auction->BuyoutOrUnitPrice)
440 {
441 // buyout
442 std::map<uint32, AuctionPosting>::node_type removedAuctionNode = auctionHouse->RemoveAuction(trans, auction);
443
444 auctionHouse->SendAuctionSold(&removedAuctionNode.mapped(), nullptr, trans);
445 auctionHouse->SendAuctionWon(&removedAuctionNode.mapped(), player, trans);
446 }
447 else
448 {
449 // place bid
451 stmt->setUInt64(0, auction->Bidder.GetCounter());
452 stmt->setUInt64(1, auction->BidAmount);
453 stmt->setUInt8(2, auction->ServerFlags.AsUnderlyingType());
454 stmt->setUInt32(3, auction->Id);
455 trans->Append(stmt);
456
457 if (auction->BidderHistory.insert(player->GetGUID()).second)
458 {
459 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_AUCTION_BIDDER);
460 stmt->setUInt32(0, auction->Id);
461 stmt->setUInt64(1, player->GetGUID().GetCounter());
462 trans->Append(stmt);
463 }
464
465 // Not sure if we must send this now.
466 if (Player* owner = ObjectAccessor::FindConnectedPlayer(auction->Owner))
467 owner->GetSession()->SendAuctionOwnerBidNotification(auction);
468 }
469
470 player->SaveInventoryAndGoldToDB(trans);
471 AddTransactionCallback(CharacterDatabase.AsyncCommitTransaction(trans)).AfterComplete(
472 [this, auctionId = placeBid.AuctionID, bidAmount = placeBid.BidAmount, auctionPlayerGuid = _player->GetGUID(), throttle](bool success)
473 {
474 if (GetPlayer() && GetPlayer()->GetGUID() == auctionPlayerGuid)
475 {
476 if (success)
477 {
478 GetPlayer()->UpdateCriteria(CriteriaType::HighestAuctionBid, bidAmount);
479 SendAuctionCommandResult(auctionId, AuctionCommand::PlaceBid, AuctionResult::Ok, throttle.DelayUntilNext);
480 }
481 else
482 SendAuctionCommandResult(auctionId, AuctionCommand::PlaceBid, AuctionResult::DatabaseError, throttle.DelayUntilNext);
483 }
484 });
485}
486
488{
489 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, removeItem.TaintedBy.has_value(), AuctionCommand::Cancel);
490 if (throttle.Throttled)
491 return;
492
494 if (!creature)
495 {
496 TC_LOG_DEBUG("network", "WORLD: HandleAuctionRemoveItem - {} not found or you can't interact with him.", removeItem.Auctioneer.ToString());
497 return;
498 }
499
500 // remove fake death
501 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
503
504 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
505
506 AuctionPosting* auction = auctionHouse->GetAuction(removeItem.AuctionID);
507 Player* player = GetPlayer();
508
509 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
510 if (auction && auction->Owner == player->GetGUID())
511 {
512 if (!auction->Bidder.IsEmpty()) // If we have a bidder, we have to send him the money he paid
513 {
514 uint64 cancelCost = CalculatePct(auction->BidAmount, 5u);
515 if (!player->HasEnoughMoney(cancelCost)) //player doesn't have enough money
516 {
518 return;
519 }
520 auctionHouse->SendAuctionCancelledToBidder(auction, trans);
521 player->ModifyMoney(-int64(cancelCost));
522 }
523
524 auctionHouse->SendAuctionRemoved(auction, player, trans);
525 }
526 else
527 {
529 //this code isn't possible ... maybe there should be assert
530 TC_LOG_ERROR("entities.player.cheat", "CHEATER : {} tried to cancel auction (id: {}) of another player or auction is NULL", player->GetGUID().ToString(), removeItem.AuctionID);
531 return;
532 }
533
534 // client bug - instead of removing auction in the UI, it only substracts 1 from visible count
535 uint32 auctionIdForClient = auction->IsCommodity() ? 0 : auction->Id;
536
537 // Now remove the auction
538 player->SaveInventoryAndGoldToDB(trans);
539 auctionHouse->RemoveAuction(trans, auction);
540 AddTransactionCallback(CharacterDatabase.AsyncCommitTransaction(trans)).AfterComplete(
541 [this, auctionIdForClient, auctionPlayerGuid = _player->GetGUID(), throttle](bool success)
542 {
543 if (GetPlayer() && GetPlayer()->GetGUID() == auctionPlayerGuid)
544 {
545 if (success)
546 SendAuctionCommandResult(auctionIdForClient, AuctionCommand::Cancel, AuctionResult::Ok, throttle.DelayUntilNext); //inform player, that auction is removed
547 else
548 SendAuctionCommandResult(0, AuctionCommand::Cancel, AuctionResult::DatabaseError, throttle.DelayUntilNext);
549 }
550 });
551}
552
554{
556 if (!creature)
557 {
558 TC_LOG_DEBUG("network", "WORLD: HandleReplicateItems - {} not found or you can't interact with him.", replicateItems.Auctioneer.ToString());
559 return;
560 }
561
562 // remove fake death
563 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
565
566 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
567
569
570 auctionHouse->BuildReplicate(response, GetPlayer(),
571 replicateItems.ChangeNumberGlobal, replicateItems.ChangeNumberCursor, replicateItems.ChangeNumberTombstone, replicateItems.Count);
572
573 response.DesiredDelay = sWorld->getIntConfig(CONFIG_AUCTION_SEARCH_DELAY) * 5;
574 response.Result = 0;
575 SendPacket(response.Write());
576}
577
579{
581 stmt->setUInt64(0, _player->GetGUID().GetCounter());
582 GetQueryProcessor().AddCallback(CharacterDatabase.AsyncQuery(stmt)).WithPreparedCallback([this](PreparedQueryResult favoriteAuctionResult)
583 {
585 if (favoriteAuctionResult)
586 {
587 favoriteItems.Items.reserve(favoriteAuctionResult->GetRowCount());
588
589 do
590 {
591 Field* fields = favoriteAuctionResult->Fetch();
592
593 WorldPackets::AuctionHouse::AuctionFavoriteInfo& item = favoriteItems.Items.emplace_back();
594 item.Order = fields[0].GetUInt32();
595 item.ItemID = fields[1].GetUInt32();
596 item.ItemLevel = fields[2].GetUInt32();
597 item.BattlePetSpeciesID = fields[3].GetUInt32();
598 item.SuffixItemNameDescriptionID = fields[4].GetUInt32();
599
600 } while (favoriteAuctionResult->NextRow());
601
602 }
603 SendPacket(favoriteItems.Write());
604 });
605}
606
608{
609 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, sellCommodity.TaintedBy.has_value(), AuctionCommand::SellItem);
610 if (throttle.Throttled)
611 return;
612
613 if (!sellCommodity.UnitPrice || sellCommodity.UnitPrice > MAX_MONEY_AMOUNT)
614 {
615 TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Player {} {} attempted to sell item with invalid price.", _player->GetName(), _player->GetGUID().ToString());
617 return;
618 }
619
620 // auction house does not deal with copper
621 if (sellCommodity.UnitPrice % SILVER)
622 {
624 return;
625 }
626
628 if (!creature)
629 {
630 TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Unit {} not found or you can't interact with him.", sellCommodity.Auctioneer.ToString());
631 return;
632 }
633
634 uint32 houseId = 0;
635 AuctionHouseEntry const* auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntry(creature->GetFaction(), &houseId);
636 if (!auctionHouseEntry)
637 {
638 TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Unit {} has wrong faction.", sellCommodity.Auctioneer.ToString());
639 return;
640 }
641
642 switch (sellCommodity.RunTime)
643 {
644 case 1 * MIN_AUCTION_TIME / MINUTE:
645 case 2 * MIN_AUCTION_TIME / MINUTE:
646 case 4 * MIN_AUCTION_TIME / MINUTE:
647 break;
648 default:
650 return;
651 }
652
653 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
655
656 // find all items for sale
657 uint64 totalCount = 0;
658 std::unordered_map<ObjectGuid, std::pair<Item*, uint64>> items2;
659
660 for (WorldPackets::AuctionHouse::AuctionItemForSale const& itemForSale : sellCommodity.Items)
661 {
662 Item* item = _player->GetItemByGuid(itemForSale.Guid);
663 if (!item)
664 {
666 return;
667 }
668
669 if (item->GetTemplate()->GetMaxStackSize() == 1)
670 {
671 // not commodity, must use different packet
673 return;
674 }
675
676 // verify that all items belong to the same bucket
677 if (!items2.empty() && AuctionsBucketKey::ForItem(item) != AuctionsBucketKey::ForItem(items2.begin()->second.first))
678 {
680 return;
681 }
682
683 if (sAuctionMgr->GetAItem(item->GetGUID()) || !item->CanBeTraded() || item->IsNotEmptyBag() ||
684 item->GetTemplate()->HasFlag(ITEM_FLAG_CONJURED) || *item->m_itemData->Expiration ||
685 item->GetCount() < itemForSale.UseCount)
686 {
688 return;
689 }
690
691 std::pair<Item*, uint64>& soldItem = items2[item->GetGUID()];
692 soldItem.first = item;
693 soldItem.second += itemForSale.UseCount;
694 if (item->GetCount() < soldItem.second)
695 {
696 // check that we have enough of this item to sell
698 return;
699 }
700
701 totalCount += itemForSale.UseCount;
702 }
703
704 if (!totalCount)
705 {
707 return;
708 }
709
710 Seconds auctionTime = Seconds(int64(std::chrono::duration_cast<Seconds>(Minutes(sellCommodity.RunTime)).count() * double(sWorld->getRate(RATE_AUCTION_TIME))));
711 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
712
713 uint64 deposit = AuctionHouseMgr::GetCommodityAuctionDeposit(items2.begin()->second.first->GetTemplate(), Minutes(sellCommodity.RunTime), totalCount);
714 if (!_player->HasEnoughMoney(deposit))
715 {
717 return;
718 }
719
720 uint32 auctionId = sObjectMgr->GenerateAuctionID();
721 AuctionPosting auction;
722 auction.Id = auctionId;
723 auction.Owner = _player->GetGUID();
724 auction.OwnerAccount = GetAccountGUID();
725 auction.BuyoutOrUnitPrice = sellCommodity.UnitPrice;
726 auction.Deposit = deposit;
728 auction.EndTime = auction.StartTime + auctionTime;
729
730 // keep track of what was cloned to undo/modify counts later
731 std::unordered_map<Item* /*original*/, std::unique_ptr<Item> /*clone*/> clones;
732 for (std::pair<ObjectGuid const, std::pair<Item*, uint64>>& it : items2)
733 {
734 Item* itemForSale;
735 if (it.second.first->GetCount() != it.second.second)
736 {
737 itemForSale = it.second.first->CloneItem(it.second.second, _player);
738 if (!itemForSale)
739 {
740 TC_LOG_ERROR("network", "CMSG_AUCTION_SELL_COMMODITY: Could not create clone of item {}", it.second.first->GetEntry());
742 return;
743 }
744
745 clones.emplace(it.second.first, itemForSale);
746 }
747 }
748
749 if (!sAuctionMgr->PendingAuctionAdd(_player, auctionHouse->GetAuctionHouseId(), auction.Id, auction.Deposit))
750 {
752 return;
753 }
754
755 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 {}",
756 _player->GetGUID().ToString(), _player->GetName(), items2.begin()->second.first->GetNameForLocaleIdx(sWorld->GetDefaultDbcLocale()),
757 ([&items2]()
758 {
759 std::stringstream ss;
760 auto itr = items2.begin();
761 ss << (itr++)->first.ToString();
762 for (; itr != items2.end(); ++itr)
763 ss << ',' << itr->first.ToString();
764 return ss.str();
765 }()).c_str(),
766 creature->GetGUID().ToString().c_str(), totalCount, sellCommodity.UnitPrice, uint32(auctionTime.count()), auctionHouse->GetAuctionHouseId());
767
769 {
770 Item* logItem = items2.begin()->second.first;
771 sLog->OutCommand(GetAccountId(), "GM {} (Account: {}) create auction: {} (Entry: {} Count: {})",
772 GetPlayerName(), GetAccountId(), logItem->GetNameForLocaleIdx(sWorld->GetDefaultDbcLocale()), logItem->GetEntry(), totalCount);
773 }
774
775 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
776
777 for (std::pair<ObjectGuid const, std::pair<Item*, uint64>> const& it : items2)
778 {
779 Item* itemForSale = it.second.first;
780 auto cloneItr = clones.find(it.second.first);
781 if (cloneItr != clones.end())
782 {
783 Item* original = itemForSale;
784 original->SetCount(original->GetCount() - uint32(it.second.second));
785 original->SetState(ITEM_CHANGED, _player);
786 _player->ItemRemovedQuestCheck(original->GetEntry(), uint32(it.second.second));
787 original->SaveToDB(trans);
788
789 itemForSale = cloneItr->second.release();
790 }
791 else
792 {
793 _player->MoveItemFromInventory(itemForSale->GetBagSlot(), itemForSale->GetSlot(), true);
794 itemForSale->DeleteFromInventoryDB(trans);
795 }
796
797 itemForSale->SaveToDB(trans);
798 auction.Items.push_back(itemForSale);
799 }
800
801 auctionHouse->AddAuction(trans, std::move(auction));
803
804 AddTransactionCallback(CharacterDatabase.AsyncCommitTransaction(trans)).AfterComplete([this, auctionId, auctionPlayerGuid = _player->GetGUID(), throttle](bool success)
805 {
806 if (GetPlayer() && GetPlayer()->GetGUID() == auctionPlayerGuid)
807 {
808 if (success)
809 {
810 GetPlayer()->UpdateCriteria(CriteriaType::ItemsPostedAtAuction, 1);
811 SendAuctionCommandResult(auctionId, AuctionCommand::SellItem, AuctionResult::Ok, throttle.DelayUntilNext);
812 }
813 else
814 SendAuctionCommandResult(0, AuctionCommand::SellItem, AuctionResult::DatabaseError, throttle.DelayUntilNext);
815 }
816 });
817}
818
820{
821 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, sellItem.TaintedBy.has_value(), AuctionCommand::SellItem);
822 if (throttle.Throttled)
823 return;
824
825 if (sellItem.Items.size() != 1 || sellItem.Items[0].UseCount != 1)
826 {
828 return;
829 }
830
831 if (!sellItem.MinBid && !sellItem.BuyoutPrice)
832 {
834 return;
835 }
836
837 if (sellItem.MinBid > MAX_MONEY_AMOUNT || sellItem.BuyoutPrice > MAX_MONEY_AMOUNT)
838 {
839 TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Player {} {} attempted to sell item with higher price than max gold amount.", _player->GetName(), _player->GetGUID().ToString());
841 return;
842 }
843
844 // auction house does not deal with copper
845 if (sellItem.MinBid % SILVER || sellItem.BuyoutPrice % SILVER)
846 {
848 return;
849 }
850
852 if (!creature)
853 {
854 TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Unit {} not found or you can't interact with him.", sellItem.Auctioneer.ToString());
855 return;
856 }
857
858 uint32 houseId = 0;
859 AuctionHouseEntry const* auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntry(creature->GetFaction(), &houseId);
860 if (!auctionHouseEntry)
861 {
862 TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Unit {} has wrong faction.", sellItem.Auctioneer.ToString());
863 return;
864 }
865
866 switch (sellItem.RunTime)
867 {
868 case 1 * MIN_AUCTION_TIME / MINUTE:
869 case 2 * MIN_AUCTION_TIME / MINUTE:
870 case 4 * MIN_AUCTION_TIME / MINUTE:
871 break;
872 default:
874 return;
875 }
876
877 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
879
880 Item* item = _player->GetItemByGuid(sellItem.Items[0].Guid);
881 if (!item)
882 {
884 return;
885 }
886
887 if (item->GetTemplate()->GetMaxStackSize() > 1)
888 {
889 // commodity, must use different packet
891 return;
892 }
893
894 if (sAuctionMgr->GetAItem(item->GetGUID()) || !item->CanBeTraded() || item->IsNotEmptyBag() ||
895 item->GetTemplate()->HasFlag(ITEM_FLAG_CONJURED) || *item->m_itemData->Expiration ||
896 item->GetCount() != 1)
897 {
899 return;
900 }
901
902 Seconds auctionTime = Seconds(int64(std::chrono::duration_cast<Seconds>(Minutes(sellItem.RunTime)).count() * double(sWorld->getRate(RATE_AUCTION_TIME))));
903 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
904
906 if (!_player->HasEnoughMoney(deposit))
907 {
909 return;
910 }
911
912 uint32 auctionId = sObjectMgr->GenerateAuctionID();
913
914 AuctionPosting auction;
915 auction.Id = auctionId;
916 auction.Owner = _player->GetGUID();
917 auction.OwnerAccount = GetAccountGUID();
918 auction.MinBid = sellItem.MinBid;
919 auction.BuyoutOrUnitPrice = sellItem.BuyoutPrice;
920 auction.Deposit = deposit;
921 auction.BidAmount = sellItem.MinBid;
923 auction.EndTime = auction.StartTime + auctionTime;
924
926 {
927 sLog->OutCommand(GetAccountId(), "GM {} (Account: {}) create auction: {} (Entry: {} Count: {})",
929 }
930
931 auction.Items.push_back(item);
932
933 TC_LOG_INFO("network", "CMSG_AUCTION_SELL_ITEM: {} {} is selling item {} {} to auctioneer {} with count {} with initial bid {} with buyout {} and with time {} (in sec) in auctionhouse {}",
935 creature->GetGUID().ToString(), item->GetCount(), sellItem.MinBid, sellItem.BuyoutPrice, uint32(auctionTime.count()), auctionHouse->GetAuctionHouseId());
936
937 // Add to pending auctions, or fail with insufficient funds error
938 if (!sAuctionMgr->PendingAuctionAdd(_player, auctionHouse->GetAuctionHouseId(), auctionId, auction.Deposit))
939 {
941 return;
942 }
943
944 _player->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true);
945
946 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
947 item->DeleteFromInventoryDB(trans);
948 item->SaveToDB(trans);
949
950 auctionHouse->AddAuction(trans, std::move(auction));
952 AddTransactionCallback(CharacterDatabase.AsyncCommitTransaction(trans)).AfterComplete([this, auctionId, auctionPlayerGuid = _player->GetGUID(), throttle](bool success)
953 {
954 if (GetPlayer() && GetPlayer()->GetGUID() == auctionPlayerGuid)
955 {
956 if (success)
957 {
958 GetPlayer()->UpdateCriteria(CriteriaType::ItemsPostedAtAuction, 1);
959 SendAuctionCommandResult(auctionId, AuctionCommand::SellItem, AuctionResult::Ok, throttle.DelayUntilNext);
960 }
961 else
962 SendAuctionCommandResult(0, AuctionCommand::SellItem, AuctionResult::DatabaseError, throttle.DelayUntilNext);
963 }
964 });
965}
966
968{
969 AuctionThrottleResult throttle = sAuctionMgr->CheckThrottle(_player, false);
970 if (throttle.Throttled)
971 return;
972
973 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
974
976 stmt->setUInt64(0, _player->GetGUID().GetCounter());
977 stmt->setUInt32(1, setFavoriteItem.Item.Order);
978 trans->Append(stmt);
979
980 if (!setFavoriteItem.IsNotFavorite)
981 {
982 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_FAVORITE_AUCTION);
983 stmt->setUInt64(0, _player->GetGUID().GetCounter());
984 stmt->setUInt32(1, setFavoriteItem.Item.Order);
985 stmt->setUInt32(2, setFavoriteItem.Item.ItemID);
986 stmt->setUInt32(3, setFavoriteItem.Item.ItemLevel);
987 stmt->setUInt32(4, setFavoriteItem.Item.BattlePetSpeciesID);
988 stmt->setUInt32(5, setFavoriteItem.Item.SuffixItemNameDescriptionID);
989 trans->Append(stmt);
990 }
991
992 CharacterDatabase.CommitTransaction(trans);
993}
994
995//this void causes that auction window is opened
997{
998 if (GetPlayer()->GetLevel() < sWorld->getIntConfig(CONFIG_AUCTION_LEVEL_REQ))
999 {
1001 return;
1002 }
1003
1004 AuctionHouseEntry const* ahEntry = AuctionHouseMgr::GetAuctionHouseEntry(unit->GetFaction(), nullptr);
1005 if (!ahEntry)
1006 return;
1007
1008 GetPlayer()->PlayerTalkClass->GetInteractionData().StartInteraction(guid, PlayerInteractionType::Auctioneer);
1009
1011 auctionHelloResponse.Auctioneer = guid;
1012 auctionHelloResponse.AuctionHouseID = ahEntry->ID;
1013 auctionHelloResponse.OpenForBusiness = true; // 3.3.3: 1 - AH enabled, 0 - AH disabled
1014 SendPacket(auctionHelloResponse.Write());
1015}
1016
1017void WorldSession::SendAuctionCommandResult(uint32 auctionId, AuctionCommand command, AuctionResult errorCode, Milliseconds delayForNextAction, InventoryResult bagResult /*= 0*/)
1018{
1020 auctionCommandResult.AuctionID = auctionId;
1021 auctionCommandResult.Command = AsUnderlyingType(command);
1022 auctionCommandResult.ErrorCode = AsUnderlyingType(errorCode);
1023 auctionCommandResult.BagResult = AsUnderlyingType(bagResult);
1024 auctionCommandResult.DesiredDelay = uint32(delayForNextAction.count());
1025 SendPacket(auctionCommandResult.Write());
1026}
1027
1028void WorldSession::SendAuctionClosedNotification(AuctionPosting const* auction, float mailDelay, bool sold)
1029{
1031 packet.Info.Initialize(auction);
1032 packet.ProceedsMailDelay = mailDelay;
1033 packet.Sold = sold;
1034 SendPacket(packet.Write());
1035}
1036
1038{
1040 packet.Info.Initialize(auction);
1041 packet.Bidder = auction->Bidder;
1042 packet.MinIncrement = auction->CalculateMinIncrement();
1043 SendPacket(packet.Write());
1044}
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:32
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
int64_t int64
Definition Define.h:149
uint64_t uint64
Definition Define.h:153
uint32_t uint32
Definition Define.h:154
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition Duration.h:24
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition Duration.h:28
std::chrono::minutes Minutes
Minutes shorthand typedef.
Definition Duration.h:32
InventoryResult
Definition ItemDefines.h:25
@ EQUIP_ERR_TOO_MUCH_GOLD
#define MAX_ITEM_SUBCLASS_TOTAL
@ ITEM_FLAG_CONJURED
#define MAX_ITEM_CLASS
@ ITEM_CHANGED
Definition Item.h:47
@ LANG_AUCTION_REQ
Definition Language.h:1170
#define TC_LOG_DEBUG(filterType__, message__,...)
Definition Log.h:181
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:190
#define TC_LOG_INFO(filterType__, message__,...)
Definition Log.h:184
#define sLog
Definition Log.h:156
#define sObjectMgr
Definition ObjectMgr.h:1885
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
constexpr uint64 MAX_MONEY_AMOUNT
Definition Player.h:1044
@ SILVER
@ SPELL_AURA_FEIGN_DEATH
@ UNIT_NPC_FLAG_AUCTIONEER
@ UNIT_NPC_FLAG_2_NONE
@ UNIT_STATE_DIED
Definition Unit.h:261
bool Utf8toWStr(char const *utf8str, size_t csize, wchar_t *wstr, size_t &wsize)
Definition Util.cpp:336
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition Util.h:565
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)
std::map< uint32, AuctionPosting >::node_type RemoveAuction(CharacterDatabaseTransaction trans, AuctionPosting *auction, std::map< uint32, AuctionPosting >::iterator *auctionItr=nullptr)
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 SendAuctionOutbid(AuctionPosting const *auction, ObjectGuid newBidder, uint64 newBidAmount, CharacterDatabaseTransaction trans) const
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
constexpr std::underlying_type_t< T > AsUnderlyingType() const
Definition EnumFlag.h:122
Class used to access individual fields of database query result.
Definition Field.h:94
uint32 GetUInt32() const noexcept
Definition Field.cpp:57
Definition Item.h:179
static void DeleteFromInventoryDB(CharacterDatabaseTransaction trans, ObjectGuid::LowType itemGuid)
Definition Item.cpp:1221
void SetState(ItemUpdateState state, Player *forplayer=nullptr)
Definition Item.cpp:1258
uint8 GetSlot() const
Definition Item.h:290
virtual void SaveToDB(CharacterDatabaseTransaction trans)
Definition Item.cpp:639
Item * CloneItem(uint32 count, Player const *player=nullptr) const
Definition Item.cpp:1751
bool CanBeTraded(bool mail=false, bool trade=false) const
Definition Item.cpp:1342
void SetCount(uint32 value)
Definition Item.cpp:1367
ItemTemplate const * GetTemplate() const
Definition Item.cpp:1233
UF::UpdateField< UF::ItemData, uint32(WowCS::EntityFragment::CGObject), TYPEID_ITEM > m_itemData
Definition Item.h:459
std::string GetNameForLocaleIdx(LocaleConstant locale) const override
Definition Item.cpp:565
bool IsNotEmptyBag() const
Definition Item.cpp:576
uint32 GetCount() const
Definition Item.h:283
uint8 GetBagSlot() const
Definition Item.cpp:1331
LowType GetCounter() const
Definition ObjectGuid.h:336
bool IsEmpty() const
Definition ObjectGuid.h:362
std::string ToString() const
uint32 GetEntry() const
Definition Object.h:89
void ItemRemovedQuestCheck(uint32 entry, uint32 count)
Definition Player.cpp:16640
bool ModifyMoney(int64 amount, bool sendError=true)
Definition Player.cpp:24850
Creature * GetNPCIfCanInteractWith(ObjectGuid const &guid, NPCFlags npcFlags, NPCFlags2 npcFlags2) const
Definition Player.cpp:1903
void SaveInventoryAndGoldToDB(CharacterDatabaseTransaction trans)
Definition Player.cpp:20843
void MoveItemFromInventory(uint8 bag, uint8 slot, bool update)
Definition Player.cpp:12075
Item * GetItemByGuid(ObjectGuid guid) const
Definition Player.cpp:9614
std::unique_ptr< PlayerMenu > PlayerTalkClass
Definition Player.h:2570
bool HasEnoughMoney(uint64 amount) const
Definition Player.h:1907
void setUInt32(uint8 index, uint32 value)
void setUInt64(uint8 index, uint64 value)
void setUInt8(uint8 index, uint8 value)
void AfterComplete(std::function< void(bool)> callback) &
Definition Unit.h:635
void RemoveAurasByType(AuraType auraType, std::function< bool(AuraApplication const *)> const &check, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3955
uint32 GetFaction() const override
Definition Unit.h:871
std::string const & GetName() const
Definition Object.h:342
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 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 SendAuctionCommandResult(uint32 auctionId, AuctionCommand command, AuctionResult errorCode, Milliseconds delayForNextAction, InventoryResult bagResult=InventoryResult(0))
Notifies the client of the result of his last auction operation. It is called when the player bids,...
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 SendAuctionHello(ObjectGuid guid, Unit const *unit)
void HandleAuctionGetCommodityQuote(WorldPackets::AuctionHouse::AuctionGetCommodityQuote &startCommoditiesPurchase)
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)
#define sWorld
Definition World.h:916
@ CONFIG_AUCTION_LEVEL_REQ
Definition World.h:326
@ CONFIG_AUCTION_SEARCH_DELAY
Definition World.h:415
@ RATE_AUCTION_TIME
Definition World.h:512
SystemTimePoint GetSystemTime()
Current chrono system_clock time point.
Definition GameTime.cpp:62
TimePoint Now()
Current chrono steady_clock time point.
Definition GameTime.cpp:67
TC_GAME_API Player * FindConnectedPlayer(ObjectGuid const &)
@ RBAC_PERM_LOG_GM_TRADE
Definition RBAC.h:64
bool IsCommodity() const
std::vector< Item * > Items
static uint64 CalculateMinIncrement(uint64 bidAmount)
EnumFlag< AuctionPostingServerFlag > ServerFlags
ObjectGuid OwnerAccount
SystemTimePoint StartTime
GuidUnorderedSet BidderHistory
SystemTimePoint EndTime
static AuctionsBucketKey ForItem(Item const *item)
uint32 GetMaxStackSize() const
bool HasFlag(ItemFlags flag) const
char const * GetDefaultLocaleName() const