fix(Core/AuctionHouse): Fix AH searches with high number of auctions (#13467)

Fix AH searches with high number of auctions
This commit is contained in:
Mickaël Mauger
2023-06-27 20:11:21 +02:00
committed by GitHub
parent cfc15abb16
commit 6edcf05cc2
10 changed files with 91 additions and 118 deletions

View File

@@ -113,7 +113,6 @@ bool LoadRealmInfo(Acore::Asio::IoContext& ioContext);
AsyncAcceptor* StartRaSocketAcceptor(Acore::Asio::IoContext& ioContext); AsyncAcceptor* StartRaSocketAcceptor(Acore::Asio::IoContext& ioContext);
void ShutdownCLIThread(std::thread* cliThread); void ShutdownCLIThread(std::thread* cliThread);
void AuctionListingRunnable(); void AuctionListingRunnable();
void ShutdownAuctionListingThread(std::thread* thread);
void WorldUpdateLoop(); void WorldUpdateLoop();
variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, [[maybe_unused]] std::string& cfg_service); variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, [[maybe_unused]] std::string& cfg_service);
@@ -398,9 +397,9 @@ int main(int argc, char** argv)
cliThread.reset(new std::thread(CliThread), &ShutdownCLIThread); cliThread.reset(new std::thread(CliThread), &ShutdownCLIThread);
} }
// Launch CliRunnable thread // Launch auction listing thread
std::shared_ptr<std::thread> auctionLisingThread; std::shared_ptr<std::thread> auctionListingThread;
auctionLisingThread.reset(new std::thread(AuctionListingRunnable), auctionListingThread.reset(new std::thread(AuctionListingRunnable),
[](std::thread* thr) [](std::thread* thr)
{ {
thr->join(); thr->join();
@@ -717,42 +716,41 @@ void AuctionListingRunnable()
while (!World::IsStopped()) while (!World::IsStopped())
{ {
if (AsyncAuctionListingMgr::IsAuctionListingAllowed()) Milliseconds diff = AsyncAuctionListingMgr::GetDiff();
AsyncAuctionListingMgr::ResetDiff();
if (!AsyncAuctionListingMgr::GetTempList().empty() || !AsyncAuctionListingMgr::GetList().empty())
{ {
uint32 diff = AsyncAuctionListingMgr::GetDiff();
AsyncAuctionListingMgr::ResetDiff();
if (AsyncAuctionListingMgr::GetTempList().size() || AsyncAuctionListingMgr::GetList().size())
{ {
std::lock_guard<std::mutex> guard(AsyncAuctionListingMgr::GetLock()); std::lock_guard<std::mutex> guard(AsyncAuctionListingMgr::GetTempLock());
for (auto const& delayEvent: AsyncAuctionListingMgr::GetTempList())
AsyncAuctionListingMgr::GetList().emplace_back(delayEvent);
AsyncAuctionListingMgr::GetTempList().clear();
}
for (auto& itr: AsyncAuctionListingMgr::GetList())
{
if (itr._pickupTimer <= diff)
{ {
std::lock_guard<std::mutex> guard(AsyncAuctionListingMgr::GetTempLock()); itr._pickupTimer = Milliseconds::zero();
for (auto const& delayEvent : AsyncAuctionListingMgr::GetTempList())
AsyncAuctionListingMgr::GetList().emplace_back(delayEvent);
AsyncAuctionListingMgr::GetTempList().clear();
} }
else
for (auto& itr : AsyncAuctionListingMgr::GetList())
{ {
if (itr._msTimer <= diff) itr._pickupTimer -= diff;
itr._msTimer = 0;
else
itr._msTimer -= diff;
} }
}
for (std::list<AuctionListItemsDelayEvent>::iterator itr = AsyncAuctionListingMgr::GetList().begin(); itr != AsyncAuctionListingMgr::GetList().end(); ++itr) for (auto itr = AsyncAuctionListingMgr::GetList().begin(); itr != AsyncAuctionListingMgr::GetList().end(); ++itr)
{ {
if ((*itr)._msTimer != 0) if ((*itr)._pickupTimer != Milliseconds::zero())
continue; continue;
if ((*itr).Execute()) if ((*itr).Execute())
AsyncAuctionListingMgr::GetList().erase(itr); AsyncAuctionListingMgr::GetList().erase(itr);
break; break;
}
} }
} }
std::this_thread::sleep_for(1ms); std::this_thread::sleep_for(1ms);
@@ -761,15 +759,6 @@ void AuctionListingRunnable()
LOG_INFO("server", "Auction House Listing thread exiting without problems."); LOG_INFO("server", "Auction House Listing thread exiting without problems.");
} }
void ShutdownAuctionListingThread(std::thread* thread)
{
if (thread)
{
thread->join();
delete thread;
}
}
variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, [[maybe_unused]] std::string& configService) variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, [[maybe_unused]] std::string& configService)
{ {
options_description all("Allowed options"); options_description all("Allowed options");

View File

@@ -3843,6 +3843,13 @@ ChangeFaction.MaxMoney = 0
Pet.RankMod.Health = 1 Pet.RankMod.Health = 1
#
# AuctionHouse.SearchTimeout
# Description: Time (in milliseconds) after which an auction house search is discarded.
# Default: 1000 - (1 second)
AuctionHouse.SearchTimeout = 1000
# #
################################################################################################### ###################################################################################################

View File

@@ -727,7 +727,7 @@ 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*/, AuctionSortOrderVector const& sortOrder) uint32& count, uint32& totalcount, uint8 /*getAll*/, AuctionSortOrderVector const& sortOrder, Milliseconds searchTimeout)
{ {
uint32 itrcounter = 0; uint32 itrcounter = 0;
@@ -754,14 +754,11 @@ bool AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player
for (AuctionEntryMap::const_iterator itr = _auctionsMap.begin(); itr != _auctionsMap.end(); ++itr) 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 ((itrcounter++) % 100 == 0) // check condition every 100 iterations if (GetMSTimeDiff(GameTime::GetGameTimeMS(), GetTimeMS()) >= searchTimeout) // pussywizard: stop immediately if diff is high or waiting too long
{ {
if (sWorldUpdateTime.GetAverageUpdateTime() >= 30 || GetMSTimeDiff(GameTime::GetGameTimeMS(), GetTimeMS()) >= 10ms) // pussywizard: stop immediately if diff is high or waiting too long return false;
{
return false;
}
} }
} }

View File

@@ -162,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, AuctionSortOrderVector const& sortOrder); uint32& count, uint32& totalcount, uint8 getAll, AuctionSortOrderVector const& sortOrder, Milliseconds searchTimeout);
private: private:
AuctionEntryMap _auctionsMap; AuctionEntryMap _auctionsMap;
@@ -184,7 +184,6 @@ public:
AuctionHouseObject* GetAuctionsMap(uint32 factionTemplateId); AuctionHouseObject* GetAuctionsMap(uint32 factionTemplateId);
AuctionHouseObject* GetAuctionsMapByHouseId(uint8 auctionHouseId); AuctionHouseObject* GetAuctionsMapByHouseId(uint8 auctionHouseId);
AuctionHouseObject* GetBidsMap(uint32 factionTemplateId);
Item* GetAItem(ObjectGuid itemGuid) Item* GetAItem(ObjectGuid itemGuid)
{ {

View File

@@ -668,23 +668,24 @@ void WorldSession::HandleAuctionListOwnerItems(WorldPacket& recvData)
recvData >> listfrom; // not used in fact (this list does not have page control in client) recvData >> listfrom; // not used in fact (this list does not have page control in client)
// pussywizard: // pussywizard:
const uint32 delay = 4500; const Milliseconds now = GameTime::GetGameTimeMS();
const uint32 now = GameTime::GetGameTimeMS().count();
if (_lastAuctionListOwnerItemsMSTime > now) // list is pending if (_lastAuctionListOwnerItemsMSTime > now) // list is pending
return; return;
uint32 diff = getMSTimeDiff(_lastAuctionListOwnerItemsMSTime, now);
const Milliseconds delay = Milliseconds(4500);
Milliseconds diff = GetMSTimeDiff(_lastAuctionListOwnerItemsMSTime, now);
if (diff > delay) if (diff > delay)
diff = delay; diff = delay;
_lastAuctionListOwnerItemsMSTime = now + delay; // set longest possible here, actual exectuing will change this to getMSTime of that moment _lastAuctionListOwnerItemsMSTime = now + delay; // set longest possible here, actual executing will change this to getMSTime of that moment
_player->m_Events.AddEvent(new AuctionListOwnerItemsDelayEvent(guid, _player->GetGUID(), true), _player->m_Events.CalculateTime(delay - diff)); _player->m_Events.AddEvent(new AuctionListOwnerItemsDelayEvent(guid, _player->GetGUID()), _player->m_Events.CalculateTime(delay.count() - diff.count()));
} }
void WorldSession::HandleAuctionListOwnerItemsEvent(ObjectGuid creatureGuid) void WorldSession::HandleAuctionListOwnerItemsEvent(ObjectGuid creatureGuid)
{ {
LOG_DEBUG("network", "WORLD: Received CMSG_AUCTION_LIST_OWNER_ITEMS"); LOG_DEBUG("network", "WORLD: Received CMSG_AUCTION_LIST_OWNER_ITEMS");
_lastAuctionListOwnerItemsMSTime = GameTime::GetGameTimeMS().count(); // pussywizard _lastAuctionListOwnerItemsMSTime = GameTime::GetGameTimeMS(); // pussywizard
Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(creatureGuid, UNIT_NPC_FLAG_AUCTIONEER); Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(creatureGuid, UNIT_NPC_FLAG_AUCTIONEER);
if (!creature) if (!creature)
@@ -757,17 +758,17 @@ void WorldSession::HandleAuctionListItems(WorldPacket& recvData)
} }
// pussywizard: // pussywizard:
const uint32 delay = 2000; const Milliseconds delay = 2s;
const uint32 now = GameTime::GetGameTimeMS().count(); const Milliseconds now = GameTime::GetGameTimeMS();
uint32 diff = getMSTimeDiff(_lastAuctionListItemsMSTime, now); Milliseconds 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, AsyncAuctionListingMgr::GetTempList().emplace_back(delay - diff, _player->GetGUID(), guid, searchedname, listfrom, levelmin, levelmax, usable, auctionSlotID,
auctionMainCategory, auctionSubCategory, quality, getAll, sortOrder)); auctionMainCategory, auctionSubCategory, quality, getAll, sortOrder);
} }
void WorldSession::HandleAuctionListPendingSales(WorldPacket& recvData) void WorldSession::HandleAuctionListPendingSales(WorldPacket& recvData)

View File

@@ -22,11 +22,9 @@
#include "Player.h" #include "Player.h"
#include "SpellAuraEffects.h" #include "SpellAuraEffects.h"
uint32 AsyncAuctionListingMgr::auctionListingDiff = 0; Milliseconds AsyncAuctionListingMgr::auctionListingDiff = Milliseconds::zero();
bool AsyncAuctionListingMgr::auctionListingAllowed = false;
std::list<AuctionListItemsDelayEvent> AsyncAuctionListingMgr::auctionListingList; std::list<AuctionListItemsDelayEvent> AsyncAuctionListingMgr::auctionListingList;
std::list<AuctionListItemsDelayEvent> AsyncAuctionListingMgr::auctionListingListTemp; std::list<AuctionListItemsDelayEvent> AsyncAuctionListingMgr::auctionListingListTemp;
std::mutex AsyncAuctionListingMgr::auctionListingLock;
std::mutex AsyncAuctionListingMgr::auctionListingTempLock; std::mutex AsyncAuctionListingMgr::auctionListingTempLock;
bool AuctionListOwnerItemsDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) bool AuctionListOwnerItemsDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
@@ -60,18 +58,19 @@ bool AuctionListItemsDelayEvent::Execute()
wstrToLower(wsearchedname); wstrToLower(wsearchedname);
uint32 searchTimeout = sWorld->getIntConfig(CONFIG_AUCTION_HOUSE_SEARCH_TIMEOUT);
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, _sortOrder); count, totalcount, _getAll, _sortOrder, Milliseconds(searchTimeout));
if (!result) if (result)
return false; {
data.put<uint32>(0, count);
data.put<uint32>(0, count); data << (uint32) totalcount;
data << (uint32) totalcount; data << (uint32) 300; // clientside search cooldown [ms] (gray search button)
data << (uint32) 300; // clientside search cooldown [ms] (gray search button) plr->GetSession()->SendPacket(&data);
plr->GetSession()->SendPacket(&data); }
return true; return true;
} }

View File

@@ -25,30 +25,28 @@
class AuctionListOwnerItemsDelayEvent : public BasicEvent class AuctionListOwnerItemsDelayEvent : public BasicEvent
{ {
public: public:
AuctionListOwnerItemsDelayEvent(ObjectGuid _creatureGuid, ObjectGuid guid, bool o) : creatureGuid(_creatureGuid), playerguid(guid), owner(o) {} AuctionListOwnerItemsDelayEvent(ObjectGuid _creatureGuid, ObjectGuid guid) : creatureGuid(_creatureGuid), playerguid(guid) {}
~AuctionListOwnerItemsDelayEvent() override {} ~AuctionListOwnerItemsDelayEvent() override {}
bool Execute(uint64 e_time, uint32 p_time) override; bool Execute(uint64 e_time, uint32 p_time) override;
void Abort(uint64 /*e_time*/) override {} void Abort(uint64 /*e_time*/) override {}
bool getOwner() { return owner; }
private: private:
ObjectGuid creatureGuid; ObjectGuid creatureGuid;
ObjectGuid playerguid; ObjectGuid playerguid;
bool owner;
}; };
class AuctionListItemsDelayEvent class AuctionListItemsDelayEvent
{ {
public: public:
AuctionListItemsDelayEvent(uint32 msTimer, ObjectGuid playerguid, ObjectGuid creatureguid, std::string searchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, AuctionListItemsDelayEvent(Milliseconds pickupTimer, 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, AuctionSortOrderVector sortOrder) : 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), _pickupTimer(pickupTimer), _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) { } _auctionSlotID(auctionSlotID), _auctionMainCategory(auctionMainCategory), _auctionSubCategory(auctionSubCategory), _quality(quality), _getAll(getAll), _sortOrder(sortOrder) { }
bool Execute(); bool Execute();
uint32 _msTimer; Milliseconds _pickupTimer;
ObjectGuid _playerguid; ObjectGuid _playerguid;
ObjectGuid _creatureguid; ObjectGuid _creatureguid;
std::string _searchedname; std::string _searchedname;
@@ -67,23 +65,17 @@ public:
class AsyncAuctionListingMgr class AsyncAuctionListingMgr
{ {
public: public:
static void Update(uint32 diff) { auctionListingDiff += diff; } static void Update(Milliseconds diff) { auctionListingDiff += diff; }
static uint32 GetDiff() { return auctionListingDiff; } static Milliseconds GetDiff() { return auctionListingDiff; }
static void ResetDiff() { auctionListingDiff = 0; } static void ResetDiff() { auctionListingDiff = Milliseconds::zero(); }
static bool IsAuctionListingAllowed() { return auctionListingAllowed; }
static void SetAuctionListingAllowed(bool a) { auctionListingAllowed = a; }
static std::list<AuctionListItemsDelayEvent>& GetList() { return auctionListingList; } static std::list<AuctionListItemsDelayEvent>& GetList() { return auctionListingList; }
static std::list<AuctionListItemsDelayEvent>& GetTempList() { return auctionListingListTemp; } static std::list<AuctionListItemsDelayEvent>& GetTempList() { return auctionListingListTemp; }
static std::mutex& GetLock() { return auctionListingLock; }
static std::mutex& GetTempLock() { return auctionListingTempLock; } static std::mutex& GetTempLock() { return auctionListingTempLock; }
private: private:
static uint32 auctionListingDiff; static Milliseconds auctionListingDiff;
static bool auctionListingAllowed;
static std::list<AuctionListItemsDelayEvent> auctionListingList; static std::list<AuctionListItemsDelayEvent> auctionListingList;
static std::list<AuctionListItemsDelayEvent> auctionListingListTemp; static std::list<AuctionListItemsDelayEvent> auctionListingListTemp;
static std::mutex auctionListingLock;
static std::mutex auctionListingTempLock; static std::mutex auctionListingTempLock;
}; };

View File

@@ -1058,8 +1058,8 @@ public: // opcodes handlers
void HandleEnterPlayerVehicle(WorldPacket& data); void HandleEnterPlayerVehicle(WorldPacket& data);
void HandleUpdateProjectilePosition(WorldPacket& recvPacket); void HandleUpdateProjectilePosition(WorldPacket& recvPacket);
uint32 _lastAuctionListItemsMSTime; Milliseconds _lastAuctionListItemsMSTime;
uint32 _lastAuctionListOwnerItemsMSTime; Milliseconds _lastAuctionListOwnerItemsMSTime;
void HandleTeleportTimeout(bool updateInSessions); void HandleTeleportTimeout(bool updateInSessions);
bool HandleSocketClosed(); bool HandleSocketClosed();

View File

@@ -413,6 +413,7 @@ enum WorldIntConfigs
CONFIG_LFG_KICK_PREVENTION_TIMER, CONFIG_LFG_KICK_PREVENTION_TIMER,
CONFIG_CHANGE_FACTION_MAX_MONEY, CONFIG_CHANGE_FACTION_MAX_MONEY,
CONFIG_WATER_BREATH_TIMER, CONFIG_WATER_BREATH_TIMER,
CONFIG_AUCTION_HOUSE_SEARCH_TIMEOUT,
INT_CONFIG_VALUE_COUNT INT_CONFIG_VALUE_COUNT
}; };

View File

@@ -1285,6 +1285,8 @@ void World::LoadConfigSettings(bool reload)
_bool_configs[CONFIG_ALLOWS_RANK_MOD_FOR_PET_HEALTH] = sConfigMgr->GetOption<bool>("Pet.RankMod.Health", true); _bool_configs[CONFIG_ALLOWS_RANK_MOD_FOR_PET_HEALTH] = sConfigMgr->GetOption<bool>("Pet.RankMod.Health", true);
_int_configs[CONFIG_AUCTION_HOUSE_SEARCH_TIMEOUT] = sConfigMgr->GetOption<uint32>("AuctionHouse.SearchTimeout", 1000);
///- Read the "Data" directory from the config file ///- Read the "Data" directory from the config file
std::string dataPath = sConfigMgr->GetOption<std::string>("DataDir", "./"); std::string dataPath = sConfigMgr->GetOption<std::string>("DataDir", "./");
if (dataPath.empty() || (dataPath.at(dataPath.length() - 1) != '/' && dataPath.at(dataPath.length() - 1) != '\\')) if (dataPath.empty() || (dataPath.at(dataPath.length() - 1) != '/' && dataPath.at(dataPath.length() - 1) != '\\'))
@@ -2349,41 +2351,27 @@ void World::Update(uint32 diff)
ResetGuildCap(); ResetGuildCap();
} }
// pussywizard: // pussywizard: handle auctions when the timer has passed
// acquire mutex now, this is kind of waiting for listing thread to finish it's work (since it can't process next packet) if (_timers[WUPDATE_AUCTIONS].Passed())
// so we don't have to do it in every packet that modifies auctions
AsyncAuctionListingMgr::SetAuctionListingAllowed(false);
{ {
std::lock_guard<std::mutex> guard(AsyncAuctionListingMgr::GetLock()); METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update expired auctions"));
// pussywizard: handle auctions when the timer has passed _timers[WUPDATE_AUCTIONS].Reset();
if (_timers[WUPDATE_AUCTIONS].Passed())
{
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update expired auctions"));
_timers[WUPDATE_AUCTIONS].Reset(); // pussywizard: handle expired auctions, auctions expired when realm was offline are also handled here (not during loading when many required things aren't loaded yet)
sAuctionMgr->Update();
// pussywizard: handle expired auctions, auctions expired when realm was offline are also handled here (not during loading when many required things aren't loaded yet)
sAuctionMgr->Update();
}
AsyncAuctionListingMgr::Update(diff);
if (currentGameTime > _mail_expire_check_timer)
{
sObjectMgr->ReturnOrDeleteOldMails(true);
_mail_expire_check_timer = currentGameTime + 6h;
}
{
/// <li> Handle session updates when the timer has passed
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update sessions"));
UpdateSessions(diff);
}
} }
// end of section with mutex AsyncAuctionListingMgr::Update(Milliseconds(diff));
AsyncAuctionListingMgr::SetAuctionListingAllowed(true);
if (currentGameTime > _mail_expire_check_timer)
{
sObjectMgr->ReturnOrDeleteOldMails(true);
_mail_expire_check_timer = currentGameTime + 6h;
}
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update sessions"));
UpdateSessions(diff);
/// <li> Handle weather updates when the timer has passed /// <li> Handle weather updates when the timer has passed
if (_timers[WUPDATE_WEATHERS].Passed()) if (_timers[WUPDATE_WEATHERS].Passed())