[11396] Auction: server side sorting and get all auctions feature.

This commit is contained in:
TOM_RUS 2011-04-26 04:04:05 +04:00
parent 0f7aaa865a
commit 66ba7d2c49
5 changed files with 394 additions and 186 deletions

View file

@ -615,7 +615,7 @@ void WorldSession::HandleAuctionListBidderItems( WorldPacket & recv_data )
recv_data >> outbiddedCount;
if (recv_data.size() != (16 + outbiddedCount * 4))
{
sLog.outError("Client sent bad opcode!!! with count: %u and size : %lu (must be: %u)", outbiddedCount, (unsigned long)recv_data.size(),(16 + outbiddedCount * 4 ));
sLog.outError("Client sent bad opcode!!! with count: %u and size : %u (must be: %u)", outbiddedCount, (uint32)recv_data.size(), (16 + outbiddedCount * 4));
outbiddedCount = 0;
}
@ -651,7 +651,7 @@ void WorldSession::HandleAuctionListBidderItems( WorldPacket & recv_data )
auctionHouse->BuildListBidderItems(data, pl, count, totalcount);
data.put<uint32>(0, count); // add count to placeholder
data << uint32(totalcount);
data << uint32(300); // unk 2.3.0 delay for next list request?
data << uint32(300); // unk 2.3.0 delay for next isFull request?
SendPacket(&data);
}
@ -678,7 +678,7 @@ void WorldSession::HandleAuctionListOwnerItems( WorldPacket & recv_data )
GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
WorldPacket data(SMSG_AUCTION_OWNER_LIST_RESULT, (4+4+4));
data << (uint32) 0; // amount place holder
data << uint32(0); // amount place holder
uint32 count = 0;
uint32 totalcount = 0;
@ -686,7 +686,7 @@ void WorldSession::HandleAuctionListOwnerItems( WorldPacket & recv_data )
auctionHouse->BuildListOwnerItems(data, _player, count, totalcount);
data.put<uint32>(0, count);
data << uint32(totalcount);
data << uint32(300); // 2.3.0 delay for next list request?
data << uint32(300); // 2.3.0 delay for next isFull request?
SendPacket(&data);
}
@ -708,11 +708,23 @@ void WorldSession::HandleAuctionListItems( WorldPacket & recv_data )
recv_data >> auctionSlotID >> auctionMainCategory >> auctionSubCategory >> quality;
recv_data >> usable >> isFull >> sortCount;
if (sortCount >= MAX_AUCTION_SORT)
return;
uint8 Sort[MAX_AUCTION_SORT];
memset(Sort, MAX_AUCTION_SORT, MAX_AUCTION_SORT);
// auction columns sorting
for (uint32 i = 0; i < sortCount; ++i)
{
recv_data.read_skip<uint8>(); // column?
recv_data.read_skip<uint8>(); // direction?
uint8 column, reversed;
recv_data >> column;
if (column >= MAX_AUCTION_SORT)
return;
recv_data >> reversed;
Sort[i] = (reversed > 0) ? (column |= AUCTION_SORT_REVERSED) : column;
}
AuctionHouseEntry const* auctionHouseEntry = GetCheckedAuctionHouseForAuctioneer(auctioneerGuid);
@ -722,6 +734,14 @@ void WorldSession::HandleAuctionListItems( WorldPacket & recv_data )
// always return pointer
AuctionHouseObject* auctionHouse = sAuctionMgr.GetAuctionsMap(auctionHouseEntry);
// Sort
AuctionHouseObject::AuctionEntryMap *aucs = auctionHouse->GetAuctions();
std::list<AuctionEntry*> auctions;
for (AuctionHouseObject::AuctionEntryMap::const_iterator itr = aucs->begin(); itr != aucs->end(); ++itr)
auctions.push_back(itr->second);
AuctionSorter sorter(Sort);
auctions.sort(sorter);
// remove fake death
if (GetPlayer()->hasUnitState(UNIT_STAT_DIED))
GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
@ -741,14 +761,12 @@ void WorldSession::HandleAuctionListItems( WorldPacket & recv_data )
wstrToLower(wsearchedname);
auctionHouse->BuildListAuctionItems(data, _player,
wsearchedname, listfrom, levelmin, levelmax, usable,
auctionSlotID, auctionMainCategory, auctionSubCategory, quality,
count, totalcount);
BuildListAuctionItems(auctions, data, wsearchedname, listfrom, levelmin, levelmax, usable,
auctionSlotID, auctionMainCategory, auctionSubCategory, quality, count, totalcount, isFull);
data.put<uint32>(0, count);
data << uint32(totalcount);
data << uint32(300); // 2.3.0 delay for next list request?
data << uint32(300); // 2.3.0 delay for next isFull request?
SendPacket(&data);
}

View file

@ -623,22 +623,196 @@ void AuctionHouseObject::BuildListOwnerItems(WorldPacket& data, Player* player,
}
}
void AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player,
std::wstring const& wsearchedname, uint32 listfrom, uint32 levelmin, uint32 levelmax, uint32 usable,
uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality,
uint32& count, uint32& totalcount)
bool AuctionEntry::CompareAuctionEntry(uint32 column, const AuctionEntry *auc) const
{
int loc_idx = player->GetSession()->GetSessionDbLocaleIndex();
Item *item1 = sAuctionMgr.GetAItem(itemGuidLow);
Item *item2 = sAuctionMgr.GetAItem(auc->itemGuidLow);
Player *pl1 = NULL;
Player *pl2 = NULL;
int res = 0;
time_t currentTime = time(NULL);
for (AuctionEntryMap::const_iterator itr = AuctionsMap.begin();itr != AuctionsMap.end();++itr)
switch (column)
{
AuctionEntry *Aentry = itr->second;
case 0: // level = 0
if (!item1 || !item2)
break;
if (item1->GetProto()->RequiredLevel < item2->GetProto()->RequiredLevel)
return true;
else if (item1->GetProto()->RequiredLevel > item2->GetProto()->RequiredLevel)
return false;
break;
case 1: // quality = 1
if (!item1 || !item2)
break;
if (item1->GetProto()->Quality < item2->GetProto()->Quality)
return true;
else if (item1->GetProto()->Quality > item2->GetProto()->Quality)
return false;
break;
case 2: // buyoutthenbid = 2
if (buyout)
{
if (buyout < auc->buyout)
return true;
else if (buyout > auc->buyout)
return false;
}
else
{
if (bid < auc->bid)
return true;
else if (bid > auc->bid)
return false;
}
break;
case 3: // duration = 3
if ((expireTime - currentTime) < (auc->expireTime - currentTime))
return true;
else if ((expireTime - currentTime) > (auc->expireTime - currentTime))
return false;
break;
case 4: // status = 4
if (bidder < auc->bidder)
return true;
else if (bidder > auc->bidder)
return false;
break;
case 5: // name = 5
if (!item1 || !item2)
break;
res = strcmp(item1->GetProto()->Name1, item2->GetProto()->Name1);
if (res < 0)
return true;
else if (res > 0)
return false;
break;
case 6: // minbidbuyout = 6
if (bid)
{
if (bid < auc->bid)
return true;
else if (bid > auc->bid)
return false;
}
else if (startbid)
{
if (startbid < auc->startbid)
return true;
else if (startbid > auc->startbid)
return false;
}
else
{
if (buyout < auc->buyout)
return true;
else if (buyout > auc->buyout)
return false;
}
break;
case 7: // seller = 7
pl1 = sObjectMgr.GetPlayer(ObjectGuid(HIGHGUID_PLAYER, owner));
pl2 = sObjectMgr.GetPlayer(ObjectGuid(HIGHGUID_PLAYER, auc->owner));
if (!pl1 || !pl2)
break;
res = strcmp(pl1->GetName(), pl2->GetName());
if (res < 0)
return true;
else if (res > 0)
return false;
break;
case 8: // bid = 8
if (bid)
{
if (bid < auc->bid)
return true;
else if (bid > auc->bid)
return false;
}
else
{
if (startbid < auc->startbid)
return true;
else if (startbid > auc->startbid)
return false;
}
break;
case 9: // quantity = 9
if (!item1 || !item2)
break;
if (item1->GetCount() < item2->GetCount())
return true;
else if (item1->GetCount() > item2->GetCount())
return false;
break;
case 10: // buyout = 10
if (buyout < auc->buyout)
return true;
else if (buyout > auc->buyout)
return false;
break;
case 11: // unused = 11
break;
default:
break;
}
if (Id < auc->Id)
return true;
else if (Id > auc->Id)
return false;
return false;
}
bool AuctionSorter::operator()(const AuctionEntry *auc1, const AuctionEntry *auc2) const
{
bool result = false;
uint32 column = 0;
for (uint32 i = 0; i < MAX_AUCTION_SORT; ++i)
{
if (m_sort[i] == MAX_AUCTION_SORT) // end of sort
{
column = m_sort[0]; // use main column
break;
}
column = m_sort[i];
result = auc1->CompareAuctionEntry(column & ~AUCTION_SORT_REVERSED, auc2);
if (result)
break;
}
if (column & AUCTION_SORT_REVERSED) // reversed flag
result = !result;
return result;
}
void WorldSession::BuildListAuctionItems(std::list<AuctionEntry*> &auctions, WorldPacket& data, std::wstring const& wsearchedname, uint32 listfrom, uint32 levelmin,
uint32 levelmax, uint32 usable, uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality, uint32& count, uint32& totalcount, bool isFull)
{
int loc_idx = _player->GetSession()->GetSessionDbLocaleIndex();
for (std::list<AuctionEntry*>::const_iterator itr = auctions.begin(); itr != auctions.end();++itr)
{
AuctionEntry *Aentry = *itr;
if (Aentry->moneyDeliveryTime)
continue;
Item *item = sAuctionMgr.GetAItem(Aentry->itemGuidLow);
if (!item)
continue;
if (isFull)
{
++count;
Aentry->BuildAuctionInfo(data);
}
else
{
ItemPrototype const *proto = item->GetProto();
if (itemClass != 0xffffffff && proto->Class != itemClass)
@ -656,7 +830,7 @@ void AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player
if (levelmin != 0x00 && (proto->RequiredLevel < levelmin || (levelmax != 0x00 && proto->RequiredLevel > levelmax)))
continue;
if (usable != 0x00 && player->CanUseItem( item ) != EQUIP_ERR_OK)
if (usable != 0x00 && _player->CanUseItem(item) != EQUIP_ERR_OK)
continue;
std::string name = proto->Name1;
@ -682,6 +856,8 @@ void AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player
++count;
Aentry->BuildAuctionInfo(data);
}
}
++totalcount;
}
}

View file

@ -30,6 +30,8 @@ class Unit;
class WorldPacket;
#define MIN_AUCTION_TIME (12*HOUR)
#define MAX_AUCTION_SORT 12
#define AUCTION_SORT_REVERSED 0x10
enum AuctionError
{
@ -74,6 +76,7 @@ struct AuctionEntry
bool BuildAuctionInfo(WorldPacket & data) const;
void DeleteFromDB() const;
void SaveToDB() const;
bool CompareAuctionEntry(uint32 column, const AuctionEntry *auc) const;
};
//this class is used as auctionhouse instance
@ -89,7 +92,9 @@ class AuctionHouseObject
typedef std::map<uint32, AuctionEntry*> AuctionEntryMap;
uint32 Getcount() { return AuctionsMap.size(); }
uint32 GetCount() { return AuctionsMap.size(); }
AuctionEntryMap *GetAuctions() { return &AuctionsMap; }
void AddAuction(AuctionEntry *ah)
{
@ -113,15 +118,21 @@ class AuctionHouseObject
void BuildListBidderItems(WorldPacket& data, Player* player, uint32& count, uint32& totalcount);
void BuildListOwnerItems(WorldPacket& data, Player* player, uint32& count, uint32& totalcount);
void BuildListPendingSales(WorldPacket& data, Player* player, uint32& count);
void BuildListAuctionItems(WorldPacket& data, Player* player,
std::wstring const& searchedname, uint32 listfrom, uint32 levelmin, uint32 levelmax, uint32 usable,
uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality,
uint32& count, uint32& totalcount);
private:
AuctionEntryMap AuctionsMap;
};
class AuctionSorter
{
public:
AuctionSorter(uint8 *sort) : m_sort(sort) {}
bool operator()(const AuctionEntry *auc1, const AuctionEntry *auc2) const;
private:
uint8* m_sort;
};
class AuctionHouseMgr
{
public:

View file

@ -356,6 +356,9 @@ class MANGOS_DLL_SPEC WorldSession
void SendAuctionRemovedNotification(AuctionEntry* auction);
void SendAuctionOutbiddedMail(AuctionEntry *auction);
void SendAuctionCancelledToBidderMail(AuctionEntry *auction);
void BuildListAuctionItems(std::list<AuctionEntry*> &auctions, WorldPacket& data, std::wstring const& searchedname, uint32 listfrom, uint32 levelmin,
uint32 levelmax, uint32 usable, uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality, uint32& count, uint32& totalcount, bool isFull);
AuctionHouseEntry const* GetCheckedAuctionHouseForAuctioneer(ObjectGuid guid);
//Item Enchantment

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "11395"
#define REVISION_NR "11396"
#endif // __REVISION_NR_H__