fix(Core/AuctionHouse): Implemented sorting. Based on @r00ty-tc work. (#9011)
Fixes #8728
This commit is contained in:
@@ -34,6 +34,186 @@
|
|||||||
|
|
||||||
constexpr auto AH_MINIMUM_DEPOSIT = 100;
|
constexpr auto AH_MINIMUM_DEPOSIT = 100;
|
||||||
|
|
||||||
|
// Proof of concept, we should shift the info we're obtaining in here into AuctionEntry probably
|
||||||
|
static bool SortAuction(AuctionEntry* left, AuctionEntry* right, AuctionSortOrderVector& sortOrder, Player* player, bool checkMinBidBuyout)
|
||||||
|
{
|
||||||
|
for (auto thisOrder : sortOrder)
|
||||||
|
{
|
||||||
|
switch (thisOrder.sortOrder)
|
||||||
|
{
|
||||||
|
case AUCTION_SORT_BID:
|
||||||
|
{
|
||||||
|
if (left->bid == right->bid)
|
||||||
|
{
|
||||||
|
if (checkMinBidBuyout)
|
||||||
|
{
|
||||||
|
if (left->buyout == right->buyout)
|
||||||
|
{
|
||||||
|
if (left->startbid == right->startbid)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return thisOrder.isDesc ? left->startbid > right->startbid : left->startbid < right->startbid;
|
||||||
|
}
|
||||||
|
|
||||||
|
return thisOrder.isDesc ? left->buyout > right->buyout : left->buyout < right->buyout;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return thisOrder.isDesc ? left->bid > right->bid : left->bid < right->bid;
|
||||||
|
}
|
||||||
|
case AUCTION_SORT_BUYOUT:
|
||||||
|
case AUCTION_SORT_BUYOUT_2:
|
||||||
|
{
|
||||||
|
if (left->buyout == right->buyout)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return thisOrder.isDesc ? left->buyout > right->buyout : left->buyout < right->buyout;
|
||||||
|
}
|
||||||
|
case AUCTION_SORT_ITEM:
|
||||||
|
{
|
||||||
|
ItemTemplate const* protoLeft = sObjectMgr->GetItemTemplate(left->item_template);
|
||||||
|
ItemTemplate const* protoRight = sObjectMgr->GetItemTemplate(right->item_template);
|
||||||
|
if (!protoLeft || !protoRight)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string leftName = protoLeft->Name1;
|
||||||
|
std::string rightName = protoRight->Name1;
|
||||||
|
if (leftName.empty() || rightName.empty())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocaleConstant locale = LOCALE_enUS;
|
||||||
|
if (player && player->GetSession())
|
||||||
|
{
|
||||||
|
locale = player->GetSession()->GetSessionDbLocaleIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (locale > LOCALE_enUS)
|
||||||
|
{
|
||||||
|
if (ItemLocale const* leftIl = sObjectMgr->GetItemLocale(protoLeft->ItemId))
|
||||||
|
{
|
||||||
|
ObjectMgr::GetLocaleString(leftIl->Name, locale, leftName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ItemLocale const* rightIl = sObjectMgr->GetItemLocale(protoRight->ItemId))
|
||||||
|
{
|
||||||
|
ObjectMgr::GetLocaleString(rightIl->Name, locale, rightName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = leftName.compare(rightName);
|
||||||
|
if (result == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return thisOrder.isDesc ? result > 0 : result < 0;
|
||||||
|
}
|
||||||
|
case AUCTION_SORT_MINLEVEL:
|
||||||
|
{
|
||||||
|
ItemTemplate const* protoLeft = sObjectMgr->GetItemTemplate(left->item_template);
|
||||||
|
ItemTemplate const* protoRight = sObjectMgr->GetItemTemplate(right->item_template);
|
||||||
|
if (!protoLeft || !protoRight)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (protoLeft->RequiredLevel == protoRight->RequiredLevel)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return thisOrder.isDesc ? protoLeft->RequiredLevel > protoRight->RequiredLevel : protoLeft->RequiredLevel < protoRight->RequiredLevel;
|
||||||
|
}
|
||||||
|
case AUCTION_SORT_OWNER:
|
||||||
|
{
|
||||||
|
std::string leftName;
|
||||||
|
sObjectMgr->GetPlayerNameByGUID(left->owner.GetCounter(), leftName);
|
||||||
|
|
||||||
|
std::string rightName;
|
||||||
|
sObjectMgr->GetPlayerNameByGUID(right->owner.GetCounter(), rightName);
|
||||||
|
|
||||||
|
int result = leftName.compare(rightName);
|
||||||
|
if (result == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return thisOrder.isDesc ? result > 0 : result < 0;
|
||||||
|
}
|
||||||
|
case AUCTION_SORT_RARITY:
|
||||||
|
{
|
||||||
|
ItemTemplate const* protoLeft = sObjectMgr->GetItemTemplate(left->item_template);
|
||||||
|
ItemTemplate const* protoRight = sObjectMgr->GetItemTemplate(right->item_template);
|
||||||
|
if (!protoLeft || !protoRight)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (protoLeft->Quality == protoRight->Quality)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return thisOrder.isDesc ? protoLeft->Quality > protoRight->Quality : protoLeft->Quality < protoRight->Quality;
|
||||||
|
}
|
||||||
|
case AUCTION_SORT_STACK:
|
||||||
|
{
|
||||||
|
if (left->itemCount == right->itemCount)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!thisOrder.isDesc)
|
||||||
|
{
|
||||||
|
return (left->itemCount < right->itemCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (left->itemCount > right->itemCount);
|
||||||
|
}
|
||||||
|
case AUCTION_SORT_TIMELEFT:
|
||||||
|
{
|
||||||
|
if (left->expire_time == right->expire_time)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return thisOrder.isDesc ? left->expire_time > right->expire_time : left->expire_time < right->expire_time;
|
||||||
|
}
|
||||||
|
case AUCTION_SORT_MINBIDBUY:
|
||||||
|
{
|
||||||
|
if (left->buyout == right->buyout)
|
||||||
|
{
|
||||||
|
if (left->startbid == right->startbid)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return thisOrder.isDesc ? left->startbid > right->startbid : left->startbid < right->startbid;
|
||||||
|
}
|
||||||
|
|
||||||
|
return thisOrder.isDesc ? left->buyout > right->buyout : left->buyout < right->buyout;
|
||||||
|
}
|
||||||
|
case AUCTION_SORT_MAX:
|
||||||
|
// Such sad travis appeasement
|
||||||
|
case AUCTION_SORT_UNK4:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
AuctionHouseMgr::AuctionHouseMgr()
|
AuctionHouseMgr::AuctionHouseMgr()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -541,139 +721,192 @@ void AuctionHouseObject::BuildListOwnerItems(WorldPacket& data, Player* player,
|
|||||||
bool AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player,
|
bool AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player,
|
||||||
std::wstring const& wsearchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, uint8 usable,
|
std::wstring const& wsearchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, uint8 usable,
|
||||||
uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality,
|
uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality,
|
||||||
uint32& count, uint32& totalcount, uint8 /*getAll*/)
|
uint32& count, uint32& totalcount, uint8 /*getAll*/, AuctionSortOrderVector const& sortOrder)
|
||||||
{
|
{
|
||||||
uint32 itrcounter = 0;
|
uint32 itrcounter = 0;
|
||||||
|
|
||||||
|
std::vector<AuctionEntry*> auctionShortlist;
|
||||||
|
|
||||||
// pussywizard: optimization, this is a simplified case
|
// pussywizard: optimization, this is a simplified case
|
||||||
if (itemClass == 0xffffffff && itemSubClass == 0xffffffff && inventoryType == 0xffffffff && quality == 0xffffffff && levelmin == 0x00 && levelmax == 0x00 && usable == 0x00 && wsearchedname.empty())
|
if (itemClass == 0xffffffff && itemSubClass == 0xffffffff && inventoryType == 0xffffffff && quality == 0xffffffff && levelmin == 0x00 && levelmax == 0x00 && usable == 0x00 && wsearchedname.empty())
|
||||||
{
|
{
|
||||||
totalcount = Getcount();
|
auto itr = GetAuctionsBegin();
|
||||||
if (listfrom < totalcount)
|
for (; itr != GetAuctionsEnd(); ++itr)
|
||||||
{
|
{
|
||||||
AuctionEntryMap::iterator itr = AuctionsMap.begin();
|
auctionShortlist.push_back(itr->second);
|
||||||
std::advance(itr, listfrom);
|
}
|
||||||
for (; itr != AuctionsMap.end(); ++itr)
|
}
|
||||||
{
|
else
|
||||||
itr->second->BuildAuctionInfo(data);
|
{
|
||||||
if ((++count) >= 50)
|
time_t curTime = sWorld->GetGameTime();
|
||||||
break;
|
|
||||||
}
|
int loc_idx = player->GetSession()->GetSessionDbLocaleIndex();
|
||||||
|
int locdbc_idx = player->GetSession()->GetSessionDbcLocale();
|
||||||
|
|
||||||
|
for (AuctionEntryMap::const_iterator itr = AuctionsMap.begin(); itr != AuctionsMap.end(); ++itr)
|
||||||
|
{
|
||||||
|
if (!AsyncAuctionListingMgr::IsAuctionListingAllowed()) // pussywizard: World::Update is waiting for us...
|
||||||
|
{
|
||||||
|
if ((itrcounter++) % 100 == 0) // check condition every 100 iterations
|
||||||
|
{
|
||||||
|
if (avgDiffTracker.getAverage() >= 30 || getMSTimeDiff(World::GetGameTimeMS(), getMSTime()) >= 10) // pussywizard: stop immediately if diff is high or waiting too long
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AuctionEntry* Aentry = itr->second;
|
||||||
|
// Skip expired auctions
|
||||||
|
if (Aentry->expire_time < curTime)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Item* item = sAuctionMgr->GetAItem(Aentry->item_guid);
|
||||||
|
if (!item)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemTemplate const* proto = item->GetTemplate();
|
||||||
|
if (itemClass != 0xffffffff && proto->Class != itemClass)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemSubClass != 0xffffffff && proto->SubClass != itemSubClass)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inventoryType != 0xffffffff && proto->InventoryType != inventoryType)
|
||||||
|
{
|
||||||
|
// xinef: exception, robes are counted as chests
|
||||||
|
if (inventoryType != INVTYPE_CHEST || proto->InventoryType != INVTYPE_ROBE)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (quality != 0xffffffff && proto->Quality < quality)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (levelmin != 0x00 && (proto->RequiredLevel < levelmin || (levelmax != 0x00 && proto->RequiredLevel > levelmax)))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usable != 0x00)
|
||||||
|
{
|
||||||
|
if (player->CanUseItem(item) != EQUIP_ERR_OK)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// xinef: check already learded recipes and pets
|
||||||
|
if (proto->Spells[1].SpellTrigger == ITEM_SPELLTRIGGER_LEARN_SPELL_ID && player->HasSpell(proto->Spells[1].SpellId))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow search by suffix (ie: of the Monkey) or partial name (ie: Monkey)
|
||||||
|
// No need to do any of this if no search term was entered
|
||||||
|
if (!wsearchedname.empty())
|
||||||
|
{
|
||||||
|
std::string name = proto->Name1;
|
||||||
|
if (name.empty())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// local name
|
||||||
|
if (loc_idx >= 0)
|
||||||
|
if (ItemLocale const* il = sObjectMgr->GetItemLocale(proto->ItemId))
|
||||||
|
ObjectMgr::GetLocaleString(il->Name, loc_idx, name);
|
||||||
|
|
||||||
|
// DO NOT use GetItemEnchantMod(proto->RandomProperty) as it may return a result
|
||||||
|
// that matches the search but it may not equal item->GetItemRandomPropertyId()
|
||||||
|
// used in BuildAuctionInfo() which then causes wrong items to be listed
|
||||||
|
int32 propRefID = item->GetItemRandomPropertyId();
|
||||||
|
|
||||||
|
if (propRefID)
|
||||||
|
{
|
||||||
|
// Append the suffix to the name (ie: of the Monkey) if one exists
|
||||||
|
// These are found in ItemRandomSuffix.dbc and ItemRandomProperties.dbc
|
||||||
|
// even though the DBC name seems misleading
|
||||||
|
std::array<char const*, 16> const* suffix = nullptr;
|
||||||
|
|
||||||
|
if (propRefID < 0)
|
||||||
|
{
|
||||||
|
const ItemRandomSuffixEntry* itemRandEntry = sItemRandomSuffixStore.LookupEntry(-item->GetItemRandomPropertyId());
|
||||||
|
if (itemRandEntry)
|
||||||
|
suffix = &itemRandEntry->Name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const ItemRandomPropertiesEntry* itemRandEntry = sItemRandomPropertiesStore.LookupEntry(item->GetItemRandomPropertyId());
|
||||||
|
if (itemRandEntry)
|
||||||
|
suffix = &itemRandEntry->Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// dbc local name
|
||||||
|
if (suffix)
|
||||||
|
{
|
||||||
|
// Append the suffix (ie: of the Monkey) to the name using localization
|
||||||
|
// or default enUS if localization is invalid
|
||||||
|
name += ' ';
|
||||||
|
name += (*suffix)[locdbc_idx >= 0 ? locdbc_idx : LOCALE_enUS];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform the search (with or without suffix)
|
||||||
|
if (!Utf8FitTo(name, wsearchedname))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auctionShortlist.push_back(Aentry);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t curTime = sWorld->GetGameTime();
|
// Check if sort enabled, and first sort column is valid, if not don't sort
|
||||||
|
if (sortOrder.size() > 0)
|
||||||
int loc_idx = player->GetSession()->GetSessionDbLocaleIndex();
|
|
||||||
int locdbc_idx = player->GetSession()->GetSessionDbcLocale();
|
|
||||||
|
|
||||||
for (AuctionEntryMap::const_iterator itr = AuctionsMap.begin(); itr != AuctionsMap.end(); ++itr)
|
|
||||||
{
|
{
|
||||||
if (!AsyncAuctionListingMgr::IsAuctionListingAllowed()) // pussywizard: World::Update is waiting for us...
|
AuctionSortInfo const& sortInfo = *sortOrder.begin();
|
||||||
if ((itrcounter++) % 100 == 0) // check condition every 100 iterations
|
if (sortInfo.sortOrder >= AUCTION_SORT_MINLEVEL && sortInfo.sortOrder < AUCTION_SORT_MAX && sortInfo.sortOrder != AUCTION_SORT_UNK4)
|
||||||
if (avgDiffTracker.getAverage() >= 30 || getMSTimeDiff(World::GetGameTimeMS(), getMSTime()) >= 10) // pussywizard: stop immediately if diff is high or waiting too long
|
|
||||||
return false;
|
|
||||||
|
|
||||||
AuctionEntry* Aentry = itr->second;
|
|
||||||
// Skip expired auctions
|
|
||||||
if (Aentry->expire_time < curTime)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Item* item = sAuctionMgr->GetAItem(Aentry->item_guid);
|
|
||||||
if (!item)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ItemTemplate const* proto = item->GetTemplate();
|
|
||||||
|
|
||||||
if (itemClass != 0xffffffff && proto->Class != itemClass)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (itemSubClass != 0xffffffff && proto->SubClass != itemSubClass)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (inventoryType != 0xffffffff && proto->InventoryType != inventoryType)
|
|
||||||
{
|
{
|
||||||
// xinef: exception, robes are counted as chests
|
// Partial sort to improve performance a bit, but the last pages will burn
|
||||||
if (inventoryType != INVTYPE_CHEST || proto->InventoryType != INVTYPE_ROBE)
|
if (listfrom + 50 <= auctionShortlist.size())
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (quality != 0xffffffff && proto->Quality < quality)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (levelmin != 0x00 && (proto->RequiredLevel < levelmin || (levelmax != 0x00 && proto->RequiredLevel > levelmax)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (usable != 0x00)
|
|
||||||
{
|
|
||||||
if (player->CanUseItem(item) != EQUIP_ERR_OK)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// xinef: check already learded recipes and pets
|
|
||||||
if (proto->Spells[1].SpellTrigger == ITEM_SPELLTRIGGER_LEARN_SPELL_ID && player->HasSpell(proto->Spells[1].SpellId))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow search by suffix (ie: of the Monkey) or partial name (ie: Monkey)
|
|
||||||
// No need to do any of this if no search term was entered
|
|
||||||
if (!wsearchedname.empty())
|
|
||||||
{
|
|
||||||
std::string name = proto->Name1;
|
|
||||||
if (name.empty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// local name
|
|
||||||
if (loc_idx >= 0)
|
|
||||||
if (ItemLocale const* il = sObjectMgr->GetItemLocale(proto->ItemId))
|
|
||||||
ObjectMgr::GetLocaleString(il->Name, loc_idx, name);
|
|
||||||
|
|
||||||
// DO NOT use GetItemEnchantMod(proto->RandomProperty) as it may return a result
|
|
||||||
// that matches the search but it may not equal item->GetItemRandomPropertyId()
|
|
||||||
// used in BuildAuctionInfo() which then causes wrong items to be listed
|
|
||||||
int32 propRefID = item->GetItemRandomPropertyId();
|
|
||||||
|
|
||||||
if (propRefID)
|
|
||||||
{
|
{
|
||||||
// Append the suffix to the name (ie: of the Monkey) if one exists
|
std::partial_sort(auctionShortlist.begin(), auctionShortlist.begin() + listfrom + 50, auctionShortlist.end(),
|
||||||
// These are found in ItemRandomSuffix.dbc and ItemRandomProperties.dbc
|
std::bind(SortAuction, std::placeholders::_1, std::placeholders::_2, sortOrder, player, sortInfo.sortOrder == AUCTION_SORT_BID));
|
||||||
// even though the DBC name seems misleading
|
}
|
||||||
|
else
|
||||||
std::array<char const*, 16> const* suffix = nullptr;
|
{
|
||||||
|
std::sort(auctionShortlist.begin(), auctionShortlist.end(), std::bind(SortAuction, std::placeholders::_1, std::placeholders::_2, sortOrder,
|
||||||
if (propRefID < 0)
|
player, sortInfo.sortOrder == AUCTION_SORT_BID));
|
||||||
{
|
|
||||||
const ItemRandomSuffixEntry* itemRandEntry = sItemRandomSuffixStore.LookupEntry(-item->GetItemRandomPropertyId());
|
|
||||||
if (itemRandEntry)
|
|
||||||
suffix = &itemRandEntry->Name;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const ItemRandomPropertiesEntry* itemRandEntry = sItemRandomPropertiesStore.LookupEntry(item->GetItemRandomPropertyId());
|
|
||||||
if (itemRandEntry)
|
|
||||||
suffix = &itemRandEntry->Name;
|
|
||||||
}
|
|
||||||
|
|
||||||
// dbc local name
|
|
||||||
if (suffix)
|
|
||||||
{
|
|
||||||
// Append the suffix (ie: of the Monkey) to the name using localization
|
|
||||||
// or default enUS if localization is invalid
|
|
||||||
name += ' ';
|
|
||||||
name += (*suffix)[locdbc_idx >= 0 ? locdbc_idx : LOCALE_enUS];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform the search (with or without suffix)
|
|
||||||
if (!Utf8FitTo(name, wsearchedname))
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto auction : auctionShortlist)
|
||||||
|
{
|
||||||
// Add the item if no search term or if entered search term was found
|
// Add the item if no search term or if entered search term was found
|
||||||
if (count < 50 && totalcount >= listfrom)
|
if (count < 50 && totalcount >= listfrom)
|
||||||
{
|
{
|
||||||
|
Item* item = sAuctionMgr->GetAItem(auction->item_guid);
|
||||||
|
if (!item)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
++count;
|
++count;
|
||||||
Aentry->BuildAuctionInfo(data);
|
auction->BuildAuctionInfo(data);
|
||||||
}
|
}
|
||||||
++totalcount;
|
++totalcount;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,33 @@ enum AuctionHouses
|
|||||||
AUCTIONHOUSE_NEUTRAL = 7
|
AUCTIONHOUSE_NEUTRAL = 7
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum AuctionSortOrder
|
||||||
|
{
|
||||||
|
AUCTION_SORT_MINLEVEL = 0,
|
||||||
|
AUCTION_SORT_RARITY = 1,
|
||||||
|
AUCTION_SORT_BUYOUT = 2,
|
||||||
|
AUCTION_SORT_TIMELEFT = 3,
|
||||||
|
AUCTION_SORT_UNK4 = 4,
|
||||||
|
AUCTION_SORT_ITEM = 5,
|
||||||
|
AUCTION_SORT_MINBIDBUY = 6,
|
||||||
|
AUCTION_SORT_OWNER = 7,
|
||||||
|
AUCTION_SORT_BID = 8,
|
||||||
|
AUCTION_SORT_STACK = 9,
|
||||||
|
AUCTION_SORT_BUYOUT_2 = 10,
|
||||||
|
|
||||||
|
AUCTION_SORT_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AuctionSortInfo
|
||||||
|
{
|
||||||
|
AuctionSortInfo() : sortOrder(AUCTION_SORT_MAX), isDesc(true) { }
|
||||||
|
|
||||||
|
AuctionSortOrder sortOrder;
|
||||||
|
bool isDesc;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<AuctionSortInfo> AuctionSortOrderVector;
|
||||||
|
|
||||||
struct AuctionEntry
|
struct AuctionEntry
|
||||||
{
|
{
|
||||||
uint32 Id;
|
uint32 Id;
|
||||||
@@ -135,7 +162,7 @@ public:
|
|||||||
bool BuildListAuctionItems(WorldPacket& data, Player* player,
|
bool BuildListAuctionItems(WorldPacket& data, Player* player,
|
||||||
std::wstring const& searchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, uint8 usable,
|
std::wstring const& searchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, uint8 usable,
|
||||||
uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality,
|
uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality,
|
||||||
uint32& count, uint32& totalcount, uint8 getAll);
|
uint32& count, uint32& totalcount, uint8 getAll, AuctionSortOrderVector const& sortOrder);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AuctionEntryMap AuctionsMap;
|
AuctionEntryMap AuctionsMap;
|
||||||
|
|||||||
@@ -727,28 +727,40 @@ void WorldSession::HandleAuctionListItems(WorldPacket& recvData)
|
|||||||
uint8 getAll;
|
uint8 getAll;
|
||||||
recvData >> getAll;
|
recvData >> getAll;
|
||||||
|
|
||||||
// this block looks like it uses some lame byte packing or similar...
|
// Read sort block
|
||||||
uint8 unkCnt;
|
uint8 sortOrderCount;
|
||||||
recvData >> unkCnt;
|
recvData >> sortOrderCount;
|
||||||
for (uint8 i = 0; i < unkCnt; i++)
|
AuctionSortOrderVector sortOrder;
|
||||||
|
for (uint8 i = 0; i < sortOrderCount; i++)
|
||||||
{
|
{
|
||||||
recvData.read_skip<uint8>();
|
uint8 sortMode;
|
||||||
recvData.read_skip<uint8>();
|
uint8 isDesc;
|
||||||
|
recvData >> sortMode;
|
||||||
|
recvData >> isDesc;
|
||||||
|
AuctionSortInfo sortInfo;
|
||||||
|
sortInfo.isDesc = (isDesc == 1);
|
||||||
|
sortInfo.sortOrder = static_cast<AuctionSortOrder>(sortMode);
|
||||||
|
sortOrder.push_back(std::move(sortInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove fake death
|
// remove fake death
|
||||||
if (_player->HasUnitState(UNIT_STATE_DIED))
|
if (_player->HasUnitState(UNIT_STATE_DIED))
|
||||||
|
{
|
||||||
_player->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
|
_player->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
|
||||||
|
}
|
||||||
|
|
||||||
// pussywizard:
|
// pussywizard:
|
||||||
const uint32 delay = 2000;
|
const uint32 delay = 2000;
|
||||||
const uint32 now = World::GetGameTimeMS();
|
const uint32 now = World::GetGameTimeMS();
|
||||||
uint32 diff = getMSTimeDiff(_lastAuctionListItemsMSTime, now);
|
uint32 diff = getMSTimeDiff(_lastAuctionListItemsMSTime, now);
|
||||||
if (diff > delay)
|
if (diff > delay)
|
||||||
|
{
|
||||||
diff = delay;
|
diff = delay;
|
||||||
|
}
|
||||||
_lastAuctionListItemsMSTime = now + delay - diff;
|
_lastAuctionListItemsMSTime = now + delay - diff;
|
||||||
std::lock_guard<std::mutex> guard(AsyncAuctionListingMgr::GetTempLock());
|
std::lock_guard<std::mutex> guard(AsyncAuctionListingMgr::GetTempLock());
|
||||||
AsyncAuctionListingMgr::GetTempList().push_back( AuctionListItemsDelayEvent(delay - diff, _player->GetGUID(), guid, searchedname, listfrom, levelmin, levelmax, usable, auctionSlotID, auctionMainCategory, auctionSubCategory, quality, getAll) );
|
AsyncAuctionListingMgr::GetTempList().push_back(AuctionListItemsDelayEvent(delay - diff, _player->GetGUID(), guid, searchedname, listfrom, levelmin, levelmax, usable, auctionSlotID,
|
||||||
|
auctionMainCategory, auctionSubCategory, quality, getAll, sortOrder));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::HandleAuctionListPendingSales(WorldPacket& recvData)
|
void WorldSession::HandleAuctionListPendingSales(WorldPacket& recvData)
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "AsyncAuctionListing.h"
|
#include "AsyncAuctionListing.h"
|
||||||
#include "AuctionHouseMgr.h"
|
|
||||||
#include "Creature.h"
|
#include "Creature.h"
|
||||||
#include "ObjectAccessor.h"
|
#include "ObjectAccessor.h"
|
||||||
#include "Opcodes.h"
|
#include "Opcodes.h"
|
||||||
@@ -64,7 +63,7 @@ bool AuctionListItemsDelayEvent::Execute()
|
|||||||
bool result = auctionHouse->BuildListAuctionItems(data, plr,
|
bool result = auctionHouse->BuildListAuctionItems(data, plr,
|
||||||
wsearchedname, _listfrom, _levelmin, _levelmax, _usable,
|
wsearchedname, _listfrom, _levelmin, _levelmax, _usable,
|
||||||
_auctionSlotID, _auctionMainCategory, _auctionSubCategory, _quality,
|
_auctionSlotID, _auctionMainCategory, _auctionSubCategory, _quality,
|
||||||
count, totalcount, _getAll);
|
count, totalcount, _getAll, _sortOrder);
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -18,10 +18,8 @@
|
|||||||
#ifndef __ASYNCAUCTIONLISTING_H
|
#ifndef __ASYNCAUCTIONLISTING_H
|
||||||
#define __ASYNCAUCTIONLISTING_H
|
#define __ASYNCAUCTIONLISTING_H
|
||||||
|
|
||||||
#include "Common.h"
|
#include "AuctionHouseMgr.h"
|
||||||
#include "EventProcessor.h"
|
|
||||||
#include "WorldPacket.h"
|
|
||||||
#include "ObjectGuid.h"
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
class AuctionListOwnerItemsDelayEvent : public BasicEvent
|
class AuctionListOwnerItemsDelayEvent : public BasicEvent
|
||||||
@@ -43,8 +41,10 @@ private:
|
|||||||
class AuctionListItemsDelayEvent
|
class AuctionListItemsDelayEvent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AuctionListItemsDelayEvent(uint32 msTimer, ObjectGuid playerguid, ObjectGuid creatureguid, std::string searchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, uint8 usable, uint32 auctionSlotID, uint32 auctionMainCategory, uint32 auctionSubCategory, uint32 quality, uint8 getAll) :
|
AuctionListItemsDelayEvent(uint32 msTimer, ObjectGuid playerguid, ObjectGuid creatureguid, std::string searchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax,
|
||||||
_msTimer(msTimer), _playerguid(playerguid), _creatureguid(creatureguid), _searchedname(searchedname), _listfrom(listfrom), _levelmin(levelmin), _levelmax(levelmax), _usable(usable), _auctionSlotID(auctionSlotID), _auctionMainCategory(auctionMainCategory), _auctionSubCategory(auctionSubCategory), _quality(quality), _getAll(getAll) { }
|
uint8 usable, uint32 auctionSlotID, uint32 auctionMainCategory, uint32 auctionSubCategory, uint32 quality, uint8 getAll, AuctionSortOrderVector sortOrder) :
|
||||||
|
_msTimer(msTimer), _playerguid(playerguid), _creatureguid(creatureguid), _searchedname(searchedname), _listfrom(listfrom), _levelmin(levelmin), _levelmax(levelmax),_usable(usable),
|
||||||
|
_auctionSlotID(auctionSlotID), _auctionMainCategory(auctionMainCategory), _auctionSubCategory(auctionSubCategory), _quality(quality), _getAll(getAll), _sortOrder(sortOrder) { }
|
||||||
|
|
||||||
bool Execute();
|
bool Execute();
|
||||||
|
|
||||||
@@ -61,6 +61,7 @@ public:
|
|||||||
uint32 _auctionSubCategory;
|
uint32 _auctionSubCategory;
|
||||||
uint32 _quality;
|
uint32 _quality;
|
||||||
uint8 _getAll;
|
uint8 _getAll;
|
||||||
|
AuctionSortOrderVector _sortOrder;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AsyncAuctionListingMgr
|
class AsyncAuctionListingMgr
|
||||||
|
|||||||
Reference in New Issue
Block a user