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