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 "DBCStructure.h"
26#include "GameTime.h"
27#include "Item.h"
28#include "Language.h"
29#include "Log.h"
30#include "Mail.h"
31#include "ObjectAccessor.h"
32#include "ObjectMgr.h"
33#include "Player.h"
34#include "UpdateMask.h"
35#include "Util.h"
36#include "World.h"
37#include "WorldPacket.h"
38
39//void called when player click on auctioneer npc
41{
43 if (!unit)
44 {
45 TC_LOG_DEBUG("network", "WORLD: HandleAuctionHelloOpcode - Unit ({}) not found or you can't interact with him.", hello.Guid.ToString());
46 return;
47 }
48
49 // remove fake death
50 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
52
53 SendAuctionHello(hello.Guid, unit);
54}
55
56//this void causes that auction window is opened
58{
59 if (GetPlayer()->GetLevel() < sWorld->getIntConfig(CONFIG_AUCTION_LEVEL_REQ))
60 {
62 return;
63 }
64
66 if (!ahEntry)
67 return;
68
70 auctionHelloResponse.Auctioneer = guid;
71 auctionHelloResponse.AuctionHouseID = ahEntry->ID;
72 auctionHelloResponse.OpenForBusiness = true; // 3.3.3: 1 - AH enabled, 0 - AH disabled
73 SendPacket(auctionHelloResponse.Write());
74}
75
76//call this method when player bids, creates, or deletes auction
77void WorldSession::SendAuctionCommandResult(AuctionEntry const* auction, AuctionCommand command, AuctionResult errorCode, InventoryResult bagResult /*= 0*/)
78{
80 auctionCommandResult.Command = AsUnderlyingType(command);
81 auctionCommandResult.ErrorCode = AsUnderlyingType(errorCode);
82 auctionCommandResult.BagResult = AsUnderlyingType(bagResult);
83
84 if (auction)
85 {
86 auctionCommandResult.AuctionID = auction->Id;
87 if (auction->bidder)
88 auctionCommandResult.Guid = ObjectGuid::Create<HighGuid::Player>(auction->bidder);
89
90 auctionCommandResult.MinIncrement = auction->GetAuctionOutBid();
91 auctionCommandResult.Money = auction->bid;
92 }
93
94 SendPacket(auctionCommandResult.Write());
95}
96
97//this function sends notification, if bidder is online
98void WorldSession::SendAuctionBidderNotification(uint32 location, uint32 auctionId, ObjectGuid bidder, uint32 bidSum, uint32 diff, uint32 itemEntry)
99{
101 data << uint32(location);
102 data << uint32(auctionId);
103 data << bidder;
104 data << uint32(bidSum);
105 data << uint32(diff);
106 data << uint32(itemEntry);
107 data << uint32(0);
108 SendPacket(&data);
109}
110
111//this void causes on client to display: "Your auction sold"
113{
115 data << uint32(auction->Id);
116 data << uint32(auction->bid);
117 data << uint32(0); //unk
118 data << uint64(0); //unk (bidder guid?)
119 data << uint32(auction->itemEntry);
120 data << uint32(0); //unk
121 data << float(0); //unk (time?)
122 SendPacket(&data);
123}
124
125void WorldSession::SendAuctionRemovedNotification(uint32 auctionId, uint32 itemEntry, int32 randomPropertyId)
126{
128 data << uint32(auctionId);
129 data << uint32(itemEntry);
130 data << uint32(randomPropertyId);
131 SendPacket(&data);
132}
133
134//this void creates new auction and adds auction to some auctionhouse
136{
137 ObjectGuid auctioneer;
138 uint32 itemsCount, etime, bid, buyout;
139 recvData >> auctioneer;
140 recvData >> itemsCount;
141
142 ObjectGuid itemGUIDs[MAX_AUCTION_ITEMS]; // 160 slot = 4x 36 slot bag + backpack 16 slot
144 memset(count, 0, sizeof(count));
145
146 if (itemsCount > MAX_AUCTION_ITEMS)
147 {
149 recvData.rfinish();
150 return;
151 }
152
153 for (uint32 i = 0; i < itemsCount; ++i)
154 {
155 recvData >> itemGUIDs[i];
156 recvData >> count[i];
157
158 if (!itemGUIDs[i] || !count[i] || count[i] > 1000)
159 {
160 recvData.rfinish();
161 return;
162 }
163 }
164
165 recvData >> bid;
166 recvData >> buyout;
167 recvData >> etime;
168
169 if (!bid || !etime)
170 return;
171
172 if (bid > MAX_MONEY_AMOUNT || buyout > MAX_MONEY_AMOUNT)
173 {
174 TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Player {} {} attempted to sell item with higher price than max gold amount.", _player->GetName(), _player->GetGUID().ToString());
176 return;
177 }
178
180 if (!creature)
181 {
182 TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Unit ({}) not found or you can't interact with him.", auctioneer.ToString());
183 return;
184 }
185
186 AuctionHouseEntry const* auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntry(creature->GetFaction());
187 if (!auctionHouseEntry)
188 {
189 TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Unit ({}) has wrong faction.", auctioneer.ToString());
190 return;
191 }
192
193 etime *= MINUTE;
194
195 switch (etime)
196 {
197 case 1*MIN_AUCTION_TIME:
198 case 2*MIN_AUCTION_TIME:
199 case 4*MIN_AUCTION_TIME:
200 break;
201 default:
202 return;
203 }
204
205 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
207
208 Item* items[MAX_AUCTION_ITEMS];
209
210 uint32 finalCount = 0;
211 uint32 itemEntry = 0;
212
213 for (uint32 i = 0; i < itemsCount; ++i)
214 {
215 Item* item = _player->GetItemByGuid(itemGUIDs[i]);
216
217 if (!item)
218 {
220 return;
221 }
222
223 if (itemEntry == 0)
224 itemEntry = item->GetTemplate()->GetId();
225
226 if (sAuctionMgr->GetAItem(item->GetGUID().GetCounter()) || !item->CanBeTraded() || item->IsNotEmptyBag() ||
228 item->GetCount() < count[i] || itemEntry != item->GetTemplate()->GetId())
229 {
231 return;
232 }
233
234 items[i] = item;
235 finalCount += count[i];
236 }
237
238 if (!finalCount)
239 {
241 return;
242 }
243
244 // check if there are 2 identical guids, in this case user is most likely cheating
245 for (uint32 i = 0; i < itemsCount - 1; ++i)
246 {
247 for (uint32 j = i + 1; j < itemsCount; ++j)
248 {
249 if (itemGUIDs[i] == itemGUIDs[j])
250 {
252 return;
253 }
254 }
255 }
256
257 for (uint32 i = 0; i < itemsCount; ++i)
258 {
259 Item* item = items[i];
260
261 if (item->GetMaxStackCount() < finalCount)
262 {
264 return;
265 }
266 }
267
268 Item* item = items[0];
269
270 uint32 auctionTime = uint32(etime * sWorld->getRate(RATE_AUCTION_TIME));
271 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
272
273 uint32 deposit = sAuctionMgr->GetAuctionDeposit(auctionHouseEntry, etime, item, finalCount);
274 if (!_player->HasEnoughMoney(deposit))
275 {
277 return;
278 }
279
280 AuctionEntry* AH = new AuctionEntry();
281
284 else
285 {
286 CreatureData const* auctioneerData = sObjectMgr->GetCreatureData(creature->GetSpawnId());
287 if (!auctioneerData)
288 {
289 TC_LOG_ERROR("misc", "Data for auctioneer not found ({})", auctioneer.ToString());
291 delete AH;
292 return;
293 }
294
295 CreatureTemplate const* auctioneerInfo = sObjectMgr->GetCreatureTemplate(auctioneerData->id);
296 if (!auctioneerInfo)
297 {
298 TC_LOG_ERROR("misc", "Non existing auctioneer ({})", auctioneer.ToString());
300 delete AH;
301 return;
302 }
303
304 AuctionHouseEntry const* AHEntry = sAuctionMgr->GetAuctionHouseEntry(auctioneerInfo->faction);
305 AH->houseId = AHEntry->ID;
306 }
307
308 // Required stack size of auction matches to current item stack size, just move item to auctionhouse
309 if (itemsCount == 1 && item->GetCount() == count[0])
310 {
312 {
313 sLog->OutCommand(GetAccountId(), "GM {} (Account: {}) create auction: {} (Entry: {} Count: {})",
314 GetPlayerName(), GetAccountId(), item->GetNameForLocaleIdx(sWorld->GetDefaultDbcLocale()), item->GetEntry(), item->GetCount());
315 }
316
317 AH->Id = sObjectMgr->GenerateAuctionID();
318 AH->itemGUIDLow = item->GetGUID().GetCounter();
319 AH->itemEntry = item->GetEntry();
320 AH->itemCount = item->GetCount();
321 AH->owner = _player->GetGUID().GetCounter();
322 AH->startbid = bid;
323 AH->bidder = 0;
324 AH->bid = 0;
325 AH->buyout = buyout;
326 AH->expire_time = GameTime::GetGameTime() + auctionTime;
327 AH->deposit = deposit;
328 AH->etime = etime;
329 AH->auctionHouseEntry = auctionHouseEntry;
331
332 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 {}",
333 _player->GetGUID().ToString(), _player->GetName(), item->GetGUID().ToString(), item->GetNameForLocaleIdx(sWorld->GetDefaultDbcLocale()),
334 creature->GetGUID().ToString(), item->GetCount(), bid, buyout, auctionTime, AH->GetHouseId());
335
336 // Add to pending auctions, or fail with insufficient funds error
337 if (!sAuctionMgr->PendingAuctionAdd(_player, AH))
338 {
340 return;
341 }
342
343 sAuctionMgr->AddAItem(item);
344 auctionHouse->AddAuction(AH);
345 _player->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true);
346
347 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
348 item->DeleteFromInventoryDB(trans);
349 item->SaveToDB(trans);
350
351 AH->SaveToDB(trans);
353 CharacterDatabase.CommitTransaction(trans);
354
356
358 }
359 else // Required stack size of auction does not match to current item stack size, clone item and set correct stack size
360 {
361 Item* newItem = item->CloneItem(finalCount, _player);
362 if (!newItem)
363 {
364 TC_LOG_ERROR("network", "CMSG_AUCTION_SELL_ITEM: Could not create clone of item {}", item->GetEntry());
366 delete AH;
367 return;
368 }
369
371 {
372 sLog->OutCommand(GetAccountId(), "GM {} (Account: {}) create auction: {} (Entry: {} Count: {})",
373 GetPlayerName(), GetAccountId(), newItem->GetNameForLocaleIdx(sWorld->GetDefaultDbcLocale()), newItem->GetEntry(), newItem->GetCount());
374 }
375
376 AH->Id = sObjectMgr->GenerateAuctionID();
377 AH->itemGUIDLow = newItem->GetGUID().GetCounter();
378 AH->itemEntry = newItem->GetEntry();
379 AH->itemCount = newItem->GetCount();
380 AH->owner = _player->GetGUID().GetCounter();
381 AH->startbid = bid;
382 AH->bidder = 0;
383 AH->bid = 0;
384 AH->buyout = buyout;
385 AH->expire_time = GameTime::GetGameTime() + auctionTime;
386 AH->deposit = deposit;
387 AH->etime = etime;
388 AH->auctionHouseEntry = auctionHouseEntry;
390
391 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 {}",
392 _player->GetGUID().ToString(), _player->GetName(), newItem->GetGUID().ToString(), newItem->GetNameForLocaleIdx(sWorld->GetDefaultDbcLocale()),
393 creature->GetGUID().ToString(), newItem->GetCount(), bid, buyout, auctionTime, AH->GetHouseId());
394
395 // Add to pending auctions, or fail with insufficient funds error
396 if (!sAuctionMgr->PendingAuctionAdd(_player, AH))
397 {
399 return;
400 }
401
402 sAuctionMgr->AddAItem(newItem);
403 auctionHouse->AddAuction(AH);
404 for (uint32 j = 0; j < itemsCount; ++j)
405 {
406 Item* item2 = items[j];
407
408 // Item stack count equals required count, ready to delete item - cloned item will be used for auction
409 if (item2->GetCount() == count[j])
410 {
411 _player->MoveItemFromInventory(item2->GetBagSlot(), item2->GetSlot(), true);
412
413 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
414 item2->DeleteFromInventoryDB(trans);
415 item2->DeleteFromDB(trans);
416 CharacterDatabase.CommitTransaction(trans);
417 delete item2;
418 }
419 else // Item stack count is bigger than required count, update item stack count and save to database - cloned item will be used for auction
420 {
421 item2->SetCount(item2->GetCount() - count[j]);
423 _player->ItemRemovedQuestCheck(item2->GetEntry(), count[j]);
425
426 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
427 item2->SaveToDB(trans);
428 CharacterDatabase.CommitTransaction(trans);
429 }
430 }
431
432 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
433 newItem->SaveToDB(trans);
434 AH->SaveToDB(trans);
436 CharacterDatabase.CommitTransaction(trans);
437
439
441 }
442}
443
444// this function is called when client bids or buys out auction
446{
447 TC_LOG_DEBUG("network", "WORLD: Received CMSG_AUCTION_PLACE_BID");
448
449 ObjectGuid auctioneer;
450 uint32 auctionId;
451 uint32 price;
452 recvData >> auctioneer;
453 recvData >> auctionId >> price;
454
455 if (!auctionId || !price)
456 return; // check for cheaters
457
459 if (!creature)
460 {
461 TC_LOG_DEBUG("network", "WORLD: HandleAuctionPlaceBid - {} not found or you can't interact with him.", auctioneer.ToString());
462 return;
463 }
464
465 // remove fake death
466 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
468
469 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
470
471 AuctionEntry* auction = auctionHouse->GetAuction(auctionId);
472 Player* player = GetPlayer();
473
474 if (!auction || auction->owner == player->GetGUID().GetCounter())
475 {
476 //you cannot bid your own auction:
478 return;
479 }
480
481 // impossible have online own another character (use this for speedup check in case online owner)
482 ObjectGuid ownerGuid = ObjectGuid::Create<HighGuid::Player>(auction->owner);
483 Player* auction_owner = ObjectAccessor::FindPlayer(ownerGuid);
484 if (!auction_owner && sCharacterCache->GetCharacterAccountIdByGuid(ownerGuid) == player->GetSession()->GetAccountId())
485 {
486 //you cannot bid your another character auction:
488 return;
489 }
490
491 // cheating
492 if (price <= auction->bid || price < auction->startbid)
493 return;
494
495 // price too low for next bid if not buyout
496 if ((price < auction->buyout || auction->buyout == 0) &&
497 price < auction->bid + auction->GetAuctionOutBid())
498 {
499 // client already test it but just in case ...
501 return;
502 }
503
504 if (!player->HasEnoughMoney(price))
505 {
506 // client already test it but just in case ...
508 return;
509 }
510
511 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
512
513 if (price < auction->buyout || auction->buyout == 0)
514 {
515 if (auction->bidder)
516 {
517 if (auction->bidder == player->GetGUID().GetCounter())
518 player->ModifyMoney(-int32(price - auction->bid));
519 else
520 {
521 // mail to last bidder and return money
522 sAuctionMgr->SendAuctionOutbiddedMail(auction, price, GetPlayer(), trans);
523 player->ModifyMoney(-int32(price));
524 }
525 }
526 else
527 player->ModifyMoney(-int32(price));
528
529 auction->bidder = player->GetGUID().GetCounter();
530 auction->bid = price;
533 else
535
537
539 stmt->setUInt32(0, auction->bidder);
540 stmt->setUInt32(1, auction->bid);
541 stmt->setUInt8(2, auction->Flags);
542 stmt->setUInt32(3, auction->Id);
543 trans->Append(stmt);
544
545 if (auction->bidders.find(player->GetGUID()) == auction->bidders.end())
546 {
547 // save new bidder in list, and save record to db
548 auction->bidders.insert(player->GetGUID());
549 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_AUCTION_BIDDERS);
550 stmt->setUInt32(0, auction->Id);
551 stmt->setUInt32(1, auction->bidder);
552 trans->Append(stmt);
553 }
554
556 }
557 else
558 {
559 //buyout:
560 if (player->GetGUID().GetCounter() == auction->bidder)
561 player->ModifyMoney(-int32(auction->buyout - auction->bid));
562 else
563 {
564 player->ModifyMoney(-int32(auction->buyout));
565 if (auction->bidder) //buyout for bidded auction ..
566 sAuctionMgr->SendAuctionOutbiddedMail(auction, auction->buyout, GetPlayer(), trans);
567 }
568 auction->bidder = player->GetGUID().GetCounter();
569 auction->bid = auction->buyout;
572 else
574
576
577 //- Mails must be under transaction control too to prevent data loss
578 sAuctionMgr->SendAuctionSalePendingMail(auction, trans);
579 sAuctionMgr->SendAuctionSuccessfulMail(auction, trans);
580 sAuctionMgr->SendAuctionWonMail(auction, trans);
581
583
584 auction->DeleteFromDB(trans);
585
586 sAuctionMgr->RemoveAItem(auction->itemGUIDLow);
587 auctionHouse->RemoveAuction(auction);
588 }
589 player->SaveInventoryAndGoldToDB(trans);
590 CharacterDatabase.CommitTransaction(trans);
591}
592
593//this void is called when auction_owner cancels his auction
595{
596 TC_LOG_DEBUG("network", "WORLD: Received CMSG_AUCTION_REMOVE_ITEM");
597
598 ObjectGuid auctioneer;
599 uint32 auctionId;
600 recvData >> auctioneer;
601 recvData >> auctionId;
602
604 if (!creature)
605 {
606 TC_LOG_DEBUG("network", "WORLD: HandleAuctionRemoveItem - {} not found or you can't interact with him.", auctioneer.ToString());
607 return;
608 }
609
610 // remove fake death
611 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
613
614 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
615
616 AuctionEntry* auction = auctionHouse->GetAuction(auctionId);
617 Player* player = GetPlayer();
618
619 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
620 if (auction && auction->owner == player->GetGUID().GetCounter())
621 {
622 Item* pItem = sAuctionMgr->GetAItem(auction->itemGUIDLow);
623 if (pItem)
624 {
625 if (auction->bidder) // If we have a bidder, we have to send him the money he paid
626 {
627 uint32 auctionCut = auction->GetAuctionCut();
628 if (!player->HasEnoughMoney(auctionCut)) //player doesn't have enough money, maybe message needed
629 return;
630 sAuctionMgr->SendAuctionCancelledToBidderMail(auction, trans, pItem);
631 player->ModifyMoney(-int32(auctionCut));
632 }
633
634 // item will deleted or added to received mail list
636 .AddItem(pItem)
637 .SendMailTo(trans, player, auction, MAIL_CHECK_MASK_COPIED);
638 }
639 else
640 {
641 TC_LOG_ERROR("network", "Auction id: {} got non existing item (item guid : {})!!!", auction->Id, auction->itemGUIDLow);
643 return;
644 }
645 }
646 else
647 {
649 //this code isn't possible ... maybe there should be assert
650 TC_LOG_ERROR("entities.player.cheat", "CHEATER : {} tried to cancel auction (id: {}) of another player or auction is NULL", player->GetGUID().ToString(), auctionId);
651 return;
652 }
653
654 //inform player, that auction is removed
656
657 // Now remove the auction
658
659 player->SaveInventoryAndGoldToDB(trans);
660 auction->DeleteFromDB(trans);
661 CharacterDatabase.CommitTransaction(trans);
662
663 sAuctionMgr->RemoveAItem(auction->itemGUIDLow);
664 auctionHouse->RemoveAuction(auction);
665}
666
667//called when player lists his bids
669{
670 TC_LOG_DEBUG("network", "WORLD: Received CMSG_AUCTION_LIST_BIDDER_ITEMS");
671
672 ObjectGuid guid; //NPC guid
673 uint32 listfrom; //page of auctions
674 uint32 outbiddedCount; //count of outbidded auctions
675
676 recvData >> guid;
677 recvData >> listfrom; // not used in fact (this list not have page control in client)
678 recvData >> outbiddedCount;
679 if (recvData.size() != (16 + outbiddedCount * 4))
680 {
681 TC_LOG_ERROR("network", "Client sent bad opcode!!! with count: {} and size : {} (must be: {})", outbiddedCount, (unsigned long)recvData.size(), (16 + outbiddedCount * 4));
682 outbiddedCount = 0;
683 }
684
686 if (!creature)
687 {
688 TC_LOG_DEBUG("network", "WORLD: HandleAuctionListBidderItems - {} not found or you can't interact with him.", guid.ToString());
689 recvData.rfinish();
690 return;
691 }
692
693 // remove fake death
694 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
696
697 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
698
700 Player* player = GetPlayer();
701 data << uint32(0); //add 0 as count
702 uint32 count = 0;
703 uint32 totalcount = 0;
704 while (outbiddedCount > 0) //add all data, which client requires
705 {
706 --outbiddedCount;
707 uint32 outbiddedAuctionId;
708 recvData >> outbiddedAuctionId;
709 AuctionEntry* auction = auctionHouse->GetAuction(outbiddedAuctionId);
710 if (auction && auction->BuildAuctionInfo(data))
711 {
712 ++totalcount;
713 ++count;
714 }
715 }
716
717 auctionHouse->BuildListBidderItems(data, player, count, totalcount);
718 data.put<uint32>(0, count); // add count to placeholder
719 data << totalcount;
720 data << uint32(sWorld->getIntConfig(CONFIG_AUCTION_SEARCH_DELAY));
721 SendPacket(&data);
722}
723
724//this void sends player info about his auctions
726{
727 TC_LOG_DEBUG("network", "WORLD: Received CMSG_AUCTION_LIST_OWNER_ITEMS");
728
729 uint32 listfrom;
730 ObjectGuid guid;
731
732 recvData >> guid;
733 recvData >> listfrom; // not used in fact (this list not have page control in client)
734
736 if (!creature)
737 {
738 TC_LOG_DEBUG("network", "WORLD: HandleAuctionListOwnerItems - {} not found or you can't interact with him.", guid.ToString());
739 return;
740 }
741
742 // remove fake death
743 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
745
746 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
747
749 data << uint32(0); // amount place holder
750
751 uint32 count = 0;
752 uint32 totalcount = 0;
753
754 auctionHouse->BuildListOwnerItems(data, _player, count, totalcount);
755 data.put<uint32>(0, count);
756 data << uint32(totalcount);
757 data << uint32(sWorld->getIntConfig(CONFIG_AUCTION_SEARCH_DELAY));
758 SendPacket(&data);
759}
760
761//this void is called when player clicks on search button
763{
764 TC_LOG_DEBUG("network", "WORLD: Received CMSG_AUCTION_LIST_ITEMS");
765
766 std::string searchedname;
767 uint8 levelmin, levelmax, usable, getAll;
768 uint32 listfrom, auctionSlotID, auctionMainCategory, auctionSubCategory, quality;
769 ObjectGuid guid;
770
771 recvData >> guid;
772 recvData >> listfrom; // start, used for page control listing by 50 elements
773 recvData >> searchedname;
774
775 recvData >> levelmin >> levelmax;
776 recvData >> auctionSlotID >> auctionMainCategory >> auctionSubCategory;
777 recvData >> quality >> usable;
778
779 recvData >> getAll;
780
781 // this block looks like it uses some lame byte packing or similar...
782 uint8 unkCnt;
783 recvData >> unkCnt;
784 for (uint8 i = 0; i < unkCnt; i++)
785 {
786 recvData.read_skip<uint8>();
787 recvData.read_skip<uint8>();
788 }
789
791 if (!creature)
792 {
793 TC_LOG_DEBUG("network", "WORLD: HandleAuctionListItems - {} not found or you can't interact with him.", guid.ToString());
794 return;
795 }
796
797 // remove fake death
798 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
800
801 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->GetFaction());
802
803 TC_LOG_DEBUG("auctionHouse", "Auctionhouse search ({}) list from: {}, searchedname: {}, levelmin: {}, levelmax: {}, auctionSlotID: {}, auctionMainCategory: {}, auctionSubCategory: {}, quality: {}, usable: {}",
804 guid.ToString(), listfrom, searchedname, levelmin, levelmax, auctionSlotID, auctionMainCategory, auctionSubCategory, quality, usable);
805
807 uint32 count = 0;
808 uint32 totalcount = 0;
809 data << uint32(0);
810
811 // converting string that we try to find to lower case
812 std::wstring wsearchedname;
813 if (!Utf8toWStr(searchedname, wsearchedname))
814 return;
815
816 wstrToLower(wsearchedname);
817
818 auctionHouse->BuildListAuctionItems(data, _player,
819 wsearchedname, listfrom, levelmin, levelmax, usable,
820 auctionSlotID, auctionMainCategory, auctionSubCategory, quality,
821 count, totalcount, (getAll != 0 && sWorld->getIntConfig(CONFIG_AUCTION_GETALL_DELAY) != 0));
822
823 data.put<uint32>(0, count);
824 data << uint32(totalcount);
825 data << uint32(sWorld->getIntConfig(CONFIG_AUCTION_SEARCH_DELAY));
826 SendPacket(&data);
827}
828
830{
831 TC_LOG_DEBUG("network", "WORLD: Received CMSG_AUCTION_LIST_PENDING_SALES");
832
833 recvData.read_skip<uint64>();
834
835 uint32 count = 0;
836
838 data << uint32(count); // count
839 /*for (uint32 i = 0; i < count; ++i)
840 {
841 data << ""; // string
842 data << ""; // string
843 data << uint32(0);
844 data << uint32(0);
845 data << float(0);
846 }*/
847 SendPacket(&data);
848}
@ AUCTION_CANCELED
AuctionCommand
@ AUCTION_SELL_ITEM
@ AUCTION_PLACE_BID
@ AUCTION_CANCEL
AuctionEntryFlag
@ AUCTION_ENTRY_FLAG_NONE
@ AUCTION_ENTRY_FLAG_GM_LOG_BUYER
AuctionResult
@ ERR_AUCTION_NOT_ENOUGHT_MONEY
@ ERR_AUCTION_OK
@ ERR_AUCTION_HIGHER_BID
@ ERR_AUCTION_BID_OWN
@ ERR_AUCTION_ITEM_NOT_FOUND
@ ERR_AUCTION_DATABASE_ERROR
#define MIN_AUCTION_TIME
@ AUCTIONHOUSE_NEUTRAL
#define MAX_AUCTION_ITEMS
#define sAuctionMgr
#define sCharacterCache
@ CHAR_INS_AUCTION_BIDDERS
@ CHAR_UPD_AUCTION_BID
@ MINUTE
Definition Common.h:29
@ ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION
Definition DBCEnums.h:203
@ ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID
Definition DBCEnums.h:204
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
uint8_t uint8
Definition Define.h:135
int32_t int32
Definition Define.h:129
uint64_t uint64
Definition Define.h:132
uint32_t uint32
Definition Define.h:133
InventoryResult
Definition ItemDefines.h:25
@ ITEM_FLAG_CONJURED
@ ITEM_CHANGED
Definition Item.h:54
@ LANG_AUCTION_REQ
Definition Language.h:1164
#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
@ MAIL_CHECK_MASK_COPIED
This mail was copied. Do not allow making a copy of items in mail.
Definition Mail.h:50
#define sObjectMgr
Definition ObjectMgr.h:1721
uint32 const MAX_MONEY_AMOUNT
Definition Player.cpp:125
@ SPELL_AURA_FEIGN_DEATH
@ UNIT_NPC_FLAG_AUCTIONEER
@ UNIT_STATE_DIED
Definition Unit.h:234
@ ITEM_FIELD_DURATION
void wstrToLower(std::wstring &str)
Definition Util.cpp:480
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:554
static AuctionHouseEntry const * GetAuctionHouseEntry(uint32 factionTemplateId)
void BuildListBidderItems(WorldPacket &data, Player *player, uint32 &count, uint32 &totalcount)
AuctionEntry * GetAuction(uint32 id) const
void AddAuction(AuctionEntry *auction)
void BuildListAuctionItems(WorldPacket &data, Player *player, std::wstring const &searchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, uint8 usable, uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality, uint32 &count, uint32 &totalcount, bool getall=false)
void BuildListOwnerItems(WorldPacket &data, Player *player, uint32 &count, uint32 &totalcount)
bool RemoveAuction(AuctionEntry *auction)
void read_skip()
Definition ByteBuffer.h:334
void rfinish()
Definition ByteBuffer.h:320
void put(std::size_t pos, T value)
Definition ByteBuffer.h:141
size_t size() const
Definition ByteBuffer.h:413
ObjectGuid::LowType GetSpawnId() const
Definition Creature.h:92
Definition Item.h:62
std::string const & GetNameForLocaleIdx(LocaleConstant locale) const override
Definition Item.cpp:297
static void DeleteFromInventoryDB(CharacterDatabaseTransaction trans, ObjectGuid::LowType itemGuid)
Definition Item.cpp:529
void SetState(ItemUpdateState state, Player *forplayer=nullptr)
Definition Item.cpp:644
uint8 GetSlot() const
Definition Item.h:143
virtual void SaveToDB(CharacterDatabaseTransaction trans)
Definition Item.cpp:329
Item * CloneItem(uint32 count, Player const *player=nullptr) const
Definition Item.cpp:1077
bool CanBeTraded(bool mail=false, bool trade=false) const
Definition Item.cpp:727
void SetCount(uint32 value)
Definition Item.cpp:1293
ItemTemplate const * GetTemplate() const
Definition Item.cpp:541
bool IsNotEmptyBag() const
Definition Item.cpp:304
uint32 GetCount() const
Definition Item.h:136
uint8 GetBagSlot() const
Definition Item.cpp:717
uint32 GetMaxStackCount() const
Definition Item.h:138
static void DeleteFromDB(CharacterDatabaseTransaction trans, ObjectGuid::LowType itemGuid)
Definition Item.cpp:512
void SendMailTo(CharacterDatabaseTransaction trans, MailReceiver const &receiver, MailSender const &sender, MailCheckMask checked=MAIL_CHECK_MASK_NONE, uint32 deliver_delay=0)
Definition Mail.cpp:188
MailDraft & AddItem(Item *item)
Definition Mail.cpp:90
LowType GetCounter() const
Definition ObjectGuid.h:156
std::string ToString() const
uint32 GetUInt32Value(uint16 index) const
Definition Object.cpp:241
uint32 GetEntry() const
Definition Object.h:81
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
void SendUpdateToPlayer(Player *player)
Definition Object.cpp:192
void ItemRemovedQuestCheck(uint32 entry, uint32 count)
Definition Player.cpp:16099
void SaveInventoryAndGoldToDB(CharacterDatabaseTransaction trans)
Definition Player.cpp:19316
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1=0, uint32 miscValue2=0, WorldObject *ref=nullptr)
Definition Player.cpp:24914
bool ModifyMoney(int32 amount, bool sendError=true)
Definition Player.cpp:22336
WorldSession * GetSession() const
Definition Player.h:1705
bool HasEnoughMoney(uint32 amount) const
Definition Player.h:1394
void MoveItemFromInventory(uint8 bag, uint8 slot, bool update)
Definition Player.cpp:12066
Creature * GetNPCIfCanInteractWith(ObjectGuid const &guid, NPCFlags npcFlags) const
Definition Player.cpp:2126
Item * GetItemByGuid(ObjectGuid guid) const
Definition Player.cpp:9516
void setUInt32(uint8 index, uint32 value)
void setUInt8(uint8 index, uint8 value)
Definition Unit.h:783
void RemoveAurasByType(AuraType auraType, std::function< bool(AuraApplication const *)> const &check, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3788
uint32 GetFaction() const override
Definition Unit.h:987
std::string const & GetName() const
Definition Object.h:384
int32 BagResult
the bid error. Possible values are AuctionError
uint32 Money
the amount of money that the player bid in copper
ObjectGuid Guid
the GUID of the bidder for this auction.
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
uint32 MinIncrement
the sum of outbid is (1% of current bid) * 5, if the bid is too small, then this value is 1 copper.
int32 Command
the type of action that triggered this notification. Possible values are AuctionAction
void HandleAuctionListPendingSales(WorldPacket &recvData)
void HandleAuctionListItems(WorldPacket &recvData)
char const * GetTrinityString(uint32 entry) const
void HandleAuctionListOwnerItems(WorldPacket &recvData)
void SendNotification(char const *format,...) ATTR_PRINTF(2
void SendPacket(WorldPacket const *packet)
Send a packet to the client.
void SendAuctionRemovedNotification(uint32 auctionId, uint32 itemEntry, int32 randomPropertyId)
void HandleAuctionSellItem(WorldPacket &recvData)
void SendAuctionCommandResult(AuctionEntry const *auction, AuctionCommand command, AuctionResult errorCode, InventoryResult bagResult=InventoryResult(0))
Notifies the client of the result of his last auction operation. It is called when the player bids,...
void SendAuctionOwnerNotification(AuctionEntry *auction)
Player * GetPlayer() const
bool HasPermission(uint32 permissionId)
void HandleAuctionListBidderItems(WorldPacket &recvData)
uint32 GetAccountId() const
Player * _player
void SendAuctionHello(ObjectGuid guid, Unit const *unit)
void SendAuctionBidderNotification(uint32 location, uint32 auctionId, ObjectGuid bidder, uint32 bidSum, uint32 diff, uint32 item_template)
void HandleAuctionRemoveItem(WorldPacket &recvData)
void HandleAuctionPlaceBid(WorldPacket &recvData)
std::string const & GetPlayerName() const
void HandleAuctionHelloOpcode(WorldPackets::AuctionHouse::AuctionHelloRequest &packet)
@ SMSG_AUCTION_BIDDER_LIST_RESULT
Definition Opcodes.h:642
@ SMSG_AUCTION_BIDDER_NOTIFICATION
Definition Opcodes.h:635
@ SMSG_AUCTION_LIST_RESULT
Definition Opcodes.h:633
@ SMSG_AUCTION_REMOVED_NOTIFICATION
Definition Opcodes.h:682
@ SMSG_AUCTION_OWNER_LIST_RESULT
Definition Opcodes.h:634
@ SMSG_AUCTION_LIST_PENDING_SALES
Definition Opcodes.h:1197
@ SMSG_AUCTION_OWNER_NOTIFICATION
Definition Opcodes.h:636
#define sWorld
Definition World.h:901
@ CONFIG_AUCTION_GETALL_DELAY
Definition World.h:392
@ CONFIG_AUCTION_LEVEL_REQ
Definition World.h:304
@ CONFIG_AUCTION_SEARCH_DELAY
Definition World.h:393
@ RATE_AUCTION_TIME
Definition World.h:459
@ CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION
Definition World.h:100
time_t GetGameTime()
Definition GameTime.cpp:42
TC_GAME_API Player * FindPlayer(ObjectGuid const &)
@ RBAC_PERM_LOG_GM_TRADE
Definition RBAC.h:64
ObjectGuid::LowType bidder
uint32 GetAuctionOutBid() const
the sum of outbid is (1% from current bid)*5, if bid is very small, it is 1c
void DeleteFromDB(CharacterDatabaseTransaction trans) const
uint8 GetHouseId() const
AuctionHouseEntry const * auctionHouseEntry
std::unordered_set< ObjectGuid > bidders
void SaveToDB(CharacterDatabaseTransaction trans) const
ObjectGuid::LowType owner
std::string BuildAuctionMailSubject(MailAuctionAnswers response) const
uint32 GetAuctionCut() const
ObjectGuid::LowType itemGUIDLow
AuctionEntryFlag Flags
bool BuildAuctionInfo(WorldPacket &data, Item *sourceItem=nullptr) const
uint32 GetId() const
bool HasFlag(ItemFlags flag) const
uint32 id
Definition SpawnData.h:96