AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
lfg::LFGQueue Class Reference

#include "LFGQueue.h"

Public Member Functions

void AddToQueue (ObjectGuid guid, bool failedProposal=false)
 
void RemoveFromQueue (ObjectGuid guid, bool partial=false)
 
void AddQueueData (ObjectGuid guid, time_t joinTime, LfgDungeonSet const &dungeons, LfgRolesMap const &rolesMap)
 
void RemoveQueueData (ObjectGuid guid)
 
void UpdateWaitTimeAvg (int32 waitTime, uint32 dungeonId)
 
void UpdateWaitTimeTank (int32 waitTime, uint32 dungeonId)
 
void UpdateWaitTimeHealer (int32 waitTime, uint32 dungeonId)
 
void UpdateWaitTimeDps (int32 waitTime, uint32 dungeonId)
 
void UpdateQueueTimers (uint32 diff)
 
time_t GetJoinTime (ObjectGuid guid)
 
uint8 FindGroups ()
 

Private Member Functions

void SetQueueUpdateData (std::string const &strGuids, LfgRolesMap const &proposalRoles)
 
void AddToNewQueue (ObjectGuid guid, bool front)
 
void RemoveFromNewQueue (ObjectGuid guid)
 
void RemoveFromCompatibles (ObjectGuid guid)
 
void AddToCompatibles (Lfg5Guids const &key)
 
uint32 FindBestCompatibleInQueue (LfgQueueDataContainer::iterator itrQueue)
 
void UpdateBestCompatibleInQueue (LfgQueueDataContainer::iterator itrQueue, Lfg5Guids const &key)
 
LfgCompatibility FindNewGroups (const ObjectGuid &newGuid)
 
LfgCompatibility CheckCompatibility (Lfg5Guids const &checkWith, const ObjectGuid &newGuid, uint64 &foundMask, uint32 &foundCount, const std::set< Lfg5Guids > &currentCompatibles)
 

Private Attributes

uint32 m_QueueStatusTimer
 
LfgQueueDataContainer QueueDataStore
 
LfgCompatibleContainer CompatibleList
 
LfgCompatibleContainer CompatibleTempList
 
LfgWaitTimesContainer waitTimesAvgStore
 
LfgWaitTimesContainer waitTimesTankStore
 
LfgWaitTimesContainer waitTimesHealerStore
 
LfgWaitTimesContainer waitTimesDpsStore
 
LfgGuidList newToQueueStore
 
LfgGuidList restoredAfterProposal
 

Detailed Description

Stores all data related to queue

Member Function Documentation

◆ AddQueueData()

void lfg::LFGQueue::AddQueueData ( ObjectGuid  guid,
time_t  joinTime,
LfgDungeonSet const &  dungeons,
LfgRolesMap const &  rolesMap 
)
108 {
109 LOG_DEBUG("lfg", "JOINED AddQueueData: {}", guid.ToString());
110 QueueDataStore[guid] = LfgQueueData(joinTime, dungeons, rolesMap);
111 AddToQueue(guid);
112 }
#define LOG_DEBUG(filterType__,...)
Definition: Log.h:171
LfgQueueDataContainer QueueDataStore
Definition: LFGQueue.h:113
void AddToQueue(ObjectGuid guid, bool failedProposal=false)
Definition: LFGQueue.cpp:37
std::string ToString() const
Definition: ObjectGuid.cpp:47

References AddToQueue(), LOG_DEBUG, QueueDataStore, and ObjectGuid::ToString().

Referenced by lfg::LFGMgr::JoinLfg(), and lfg::LFGMgr::UpdateRoleCheck().

◆ AddToCompatibles()

void lfg::LFGQueue::AddToCompatibles ( Lfg5Guids const &  key)
private
171 {
172 LOG_DEBUG("lfg", "COMPATIBLES ADD: {}", key.toString());
173 CompatibleTempList.push_back(key);
174 }
LfgCompatibleContainer CompatibleTempList
Definition: LFGQueue.h:115

References CompatibleTempList, LOG_DEBUG, and lfg::Lfg5Guids::toString().

Referenced by CheckCompatibility().

◆ AddToNewQueue()

void lfg::LFGQueue::AddToNewQueue ( ObjectGuid  guid,
bool  front 
)
private
86 {
87 if (front)
88 {
89 LOG_DEBUG("lfg", "ADD AddToNewQueue at FRONT: {}", guid.ToString());
90 restoredAfterProposal.push_back(guid);
91 newToQueueStore.push_front(guid);
92 }
93 else
94 {
95 LOG_DEBUG("lfg", "ADD AddToNewQueue at the END: {}", guid.ToString());
96 newToQueueStore.push_back(guid);
97 }
98 }
LfgGuidList restoredAfterProposal
Definition: LFGQueue.h:122
LfgGuidList newToQueueStore
Definition: LFGQueue.h:121

References LOG_DEBUG, newToQueueStore, restoredAfterProposal, and ObjectGuid::ToString().

Referenced by AddToQueue().

◆ AddToQueue()

void lfg::LFGQueue::AddToQueue ( ObjectGuid  guid,
bool  failedProposal = false 
)
38 {
39 LOG_DEBUG("lfg", "ADD AddToQueue: {}, failed proposal: {}", guid.ToString(), failedProposal ? 1 : 0);
40 LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(guid);
41 if (itQueue == QueueDataStore.end())
42 {
43 LOG_ERROR("lfg", "LFGQueue::AddToQueue: Queue data not found for [{}]", guid.ToString());
44 return;
45 }
46 LOG_DEBUG("lfg", "AddToQueue success: {}", guid.ToString());
47 AddToNewQueue(guid, failedProposal);
48 }
#define LOG_ERROR(filterType__,...)
Definition: Log.h:159
void AddToNewQueue(ObjectGuid guid, bool front)
Definition: LFGQueue.cpp:85

References AddToNewQueue(), LOG_DEBUG, LOG_ERROR, QueueDataStore, and ObjectGuid::ToString().

Referenced by AddQueueData(), lfg::LFGMgr::RemoveProposal(), and UpdateQueueTimers().

◆ CheckCompatibility()

LfgCompatibility lfg::LFGQueue::CheckCompatibility ( Lfg5Guids const &  checkWith,
const ObjectGuid newGuid,
uint64 foundMask,
uint32 foundCount,
const std::set< Lfg5Guids > &  currentCompatibles 
)
private
248 {
249 LOG_DEBUG("lfg", "CHECK CheckCompatibility: {}, new guid: {}", checkWith.toString(), newGuid.ToString());
250 Lfg5Guids check(checkWith, false); // here newGuid is at front
251 Lfg5Guids strGuids(checkWith, false); // here guids are sorted
252 check.force_insert_front(newGuid);
253 strGuids.insert(newGuid);
254
255 if (!currentCompatibles.empty() && currentCompatibles.find(strGuids) != currentCompatibles.end())
257
258 LfgProposal proposal;
259 LfgDungeonSet proposalDungeons;
260 LfgGroupsMap proposalGroups;
261 LfgRolesMap proposalRoles;
262
263 // Check if more than one LFG group and number of players joining
264 uint8 numPlayers = 0;
265 uint8 numLfgGroups = 0;
266 ObjectGuid guid;
267 uint64 addToFoundMask = 0;
268
269 for (uint8 i = 0; i < 5 && !(guid = check.guids[i]).IsEmpty() && numLfgGroups < 2 && numPlayers <= MAXGROUPSIZE; ++i)
270 {
271 LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(guid);
272 if (itQueue == QueueDataStore.end())
273 {
274 LOG_ERROR("lfg", "LFGQueue::CheckCompatibility: [{}] is not queued but listed as queued!", guid.ToString());
275 RemoveFromQueue(guid);
277 }
278
279 // Store group so we don't need to call Mgr to get it later (if it's player group will be 0 otherwise would have joined as group)
280 for (LfgRolesMap::const_iterator it2 = itQueue->second.roles.begin(); it2 != itQueue->second.roles.end(); ++it2)
281 proposalGroups[it2->first] = itQueue->first.IsGroup() ? itQueue->first : ObjectGuid::Empty;
282
283 numPlayers += itQueue->second.roles.size();
284
285 if (sLFGMgr->IsLfgGroup(guid))
286 {
287 if (!numLfgGroups)
288 proposal.group = guid;
289 ++numLfgGroups;
290 }
291 }
292
293 if (numLfgGroups > 1)
295
296 // Group with less that MAXGROUPSIZE members always compatible
297 if (!sLFGMgr->IsTesting() && check.size() == 1 && numPlayers < MAXGROUPSIZE)
298 {
299 LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(check.front());
300 LfgRolesMap roles = itQueue->second.roles;
301 uint8 roleCheckResult = LFGMgr::CheckGroupRoles(roles);
302 strGuids.addRoles(roles);
303 itQueue->second.bestCompatible.clear(); // this may be left after a failed proposal (not cleared, because UpdateQueueTimers would try to generate it with every update)
304 //UpdateBestCompatibleInQueue(itQueue, strGuids);
305 AddToCompatibles(strGuids);
306 if (roleCheckResult && roleCheckResult <= 15)
307 foundMask |= ( (((uint64)1) << (roleCheckResult - 1)) | (((uint64)1) << (16 + roleCheckResult - 1)) | (((uint64)1) << (32 + roleCheckResult - 1)) | (((uint64)1) << (48 + roleCheckResult - 1)) );
309 }
310
311 if (numPlayers > MAXGROUPSIZE)
313
314 // If it's single group no need to check for duplicate players, ignores, bad roles or bad dungeons as it's been checked before joining
315 if (check.size() > 1)
316 {
317 for (uint8 i = 0; i < 5 && check.guids[i]; ++i)
318 {
319 const LfgRolesMap& roles = QueueDataStore[check.guids[i]].roles;
320 for (LfgRolesMap::const_iterator itRoles = roles.begin(); itRoles != roles.end(); ++itRoles)
321 {
322 LfgRolesMap::const_iterator itPlayer;
323 for (itPlayer = proposalRoles.begin(); itPlayer != proposalRoles.end(); ++itPlayer)
324 {
325 if (itRoles->first == itPlayer->first)
326 {
327 // pussywizard: LFG this means that this player was in two different LfgQueueData (in QueueDataStore), and at least one of them is a group guid, because we do checks so there aren't 2 same guids in current CHECK
328 //LOG_ERROR("lfg", "LFGQueue::CheckCompatibility: ERROR! Player multiple times in queue! [{}]", itRoles->first.ToString());
329 break;
330 }
331 else if (sLFGMgr->HasIgnore(itRoles->first, itPlayer->first))
332 break;
333 }
334 if (itPlayer == proposalRoles.end())
335 proposalRoles[itRoles->first] = itRoles->second;
336 else
337 break;
338 }
339 }
340
341 if (numPlayers != proposalRoles.size())
343
344 uint8 roleCheckResult = LFGMgr::CheckGroupRoles(proposalRoles);
345 if (!roleCheckResult || roleCheckResult > 0xF)
347
348 // now, every combination can occur only 4 times (explained in FindNewGroups)
349 if (foundMask & (((uint64)1) << (roleCheckResult - 1)))
350 {
351 if (foundMask & (((uint64)1) << (16 + roleCheckResult - 1)))
352 {
353 if (foundMask & (((uint64)1) << (32 + roleCheckResult - 1)))
354 {
355 if (foundMask & (((uint64)1) << (48 + roleCheckResult - 1)))
356 {
357 if (foundCount >= 10) // but only after finding at least 10 compatibles (this helps when there are few groups)
359 }
360 else
361 addToFoundMask |= (((uint64)1) << (48 + roleCheckResult - 1));
362 }
363 else
364 addToFoundMask |= (((uint64)1) << (32 + roleCheckResult - 1));
365 }
366 else
367 addToFoundMask |= (((uint64)1) << (16 + roleCheckResult - 1));
368 }
369 else
370 addToFoundMask |= (((uint64)1) << (roleCheckResult - 1));
371
372 proposalDungeons = QueueDataStore[check.front()].dungeons;
373 for (uint8 i = 1; i < 5 && check.guids[i]; ++i)
374 {
375 LfgDungeonSet temporal;
376 LfgDungeonSet& dungeons = QueueDataStore[check.guids[i]].dungeons;
377 std::set_intersection(proposalDungeons.begin(), proposalDungeons.end(), dungeons.begin(), dungeons.end(), std::inserter(temporal, temporal.begin()));
378 proposalDungeons = temporal;
379 }
380
381 if (proposalDungeons.empty())
383 }
384 else
385 {
386 ObjectGuid gguid = check.front();
387 const LfgQueueData& queue = QueueDataStore[gguid];
388 proposalDungeons = queue.dungeons;
389 proposalRoles = queue.roles;
390 LFGMgr::CheckGroupRoles(proposalRoles); // assing new roles
391 }
392
393 // Enough players?
394 if (!sLFGMgr->IsTesting() && numPlayers != MAXGROUPSIZE)
395 {
396 strGuids.addRoles(proposalRoles);
397 for (uint8 i = 0; i < 5 && check.guids[i]; ++i)
398 {
399 LfgQueueDataContainer::iterator itr = QueueDataStore.find(check.guids[i]);
400 if (!itr->second.bestCompatible.empty()) // update if groups don't have it empty (for empty it will be generated in UpdateQueueTimers)
401 UpdateBestCompatibleInQueue(itr, strGuids);
402 }
403 AddToCompatibles(strGuids);
404 foundMask |= addToFoundMask;
405 ++foundCount;
407 }
408
409 proposal.queues = strGuids;
410 proposal.isNew = numLfgGroups != 1;
411
412 if (!sLFGMgr->AllQueued(check)) // can't create proposal
414
415 // Create a new proposal
416 proposal.cancelTime = GameTime::GetGameTime().count() + LFG_TIME_PROPOSAL;
417 proposal.state = LFG_PROPOSAL_INITIATING;
418 proposal.leader.Clear();
419 proposal.dungeonId = Acore::Containers::SelectRandomContainerElement(proposalDungeons);
420
421 uint32 completedEncounters = 0;
422 bool leader = false;
423 for (LfgRolesMap::const_iterator itRoles = proposalRoles.begin(); itRoles != proposalRoles.end(); ++itRoles)
424 {
425 // Assing new leader
426 if (itRoles->second & PLAYER_ROLE_LEADER)
427 {
428 if (!leader || !proposal.leader || urand(0, 1))
429 proposal.leader = itRoles->first;
430 leader = true;
431 }
432 else if (!leader && (!proposal.leader || urand(0, 1)))
433 proposal.leader = itRoles->first;
434
435 // Assing player data and roles
436 LfgProposalPlayer& data = proposal.players[itRoles->first];
437 data.role = itRoles->second;
438 data.group = proposalGroups.find(itRoles->first)->second;
439 if (!proposal.isNew && data.group && data.group == proposal.group) // Player from existing group, autoaccept
440 data.accept = LFG_ANSWER_AGREE;
441
442 if (!completedEncounters && !proposal.isNew)
443 {
444 if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(proposal.dungeonId))
445 {
446 if (Player* player = ObjectAccessor::FindConnectedPlayer(itRoles->first))
447 {
448 if (player->GetMapId() == static_cast<uint32>(dungeon->map))
449 {
450 if (InstanceScript* instance = player->GetInstanceScript())
451 {
452 completedEncounters = instance->GetCompletedEncounterMask();
453 }
454 }
455 }
456 }
457 }
458 }
459
460 proposal.encounters = completedEncounters;
461
462 for (uint8 i = 0; i < 5 && proposal.queues.guids[i]; ++i)
463 RemoveFromQueue(proposal.queues.guids[i], true);
464
465 sLFGMgr->AddProposal(proposal);
466
468 }
std::uint8_t uint8
Definition: Define.h:110
std::uint32_t uint32
Definition: Define.h:108
std::uint64_t uint64
Definition: Define.h:107
uint32 urand(uint32 min, uint32 max)
Definition: Random.cpp:44
DBCStorage< LFGDungeonEntry > sLFGDungeonStore(LFGDungeonEntryfmt)
#define sLFGMgr
Definition: LFGMgr.h:638
#define MAXGROUPSIZE
Definition: Group.h:42
auto SelectRandomContainerElement(C const &container) -> typename std::add_const< decltype(*std::begin(container))>::type &
Definition: Containers.h:135
std::map< ObjectGuid, uint8 > LfgRolesMap
Definition: LFG.h:114
@ LFG_TIME_PROPOSAL
Definition: LFGMgr.h:50
@ LFG_ANSWER_AGREE
Definition: LFG.h:103
@ LFG_COMPATIBLES_WITH_LESS_PLAYERS
Definition: LFGQueue.h:36
@ LFG_INCOMPATIBLES_HAS_IGNORES
Definition: LFGQueue.h:33
@ LFG_INCOMPATIBLES_MULTIPLE_LFG_GROUPS
Definition: LFGQueue.h:32
@ LFG_INCOMPATIBLES_NO_DUNGEONS
Definition: LFGQueue.h:35
@ LFG_COMPATIBILITY_PENDING
Definition: LFGQueue.h:29
@ LFG_COMPATIBLES_MATCH
Definition: LFGQueue.h:37
@ LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS
Definition: LFGQueue.h:31
@ LFG_INCOMPATIBLES_NO_ROLES
Definition: LFGQueue.h:34
std::set< uint32 > LfgDungeonSet
Definition: LFG.h:109
std::map< ObjectGuid, ObjectGuid > LfgGroupsMap
Definition: LFG.h:115
@ PLAYER_ROLE_LEADER
Definition: LFG.h:43
@ LFG_PROPOSAL_INITIATING
Definition: LFGMgr.h:80
Player * FindConnectedPlayer(ObjectGuid const guid)
Definition: ObjectAccessor.cpp:262
Seconds GetGameTime()
Definition: GameTime.cpp:38
static uint8 CheckGroupRoles(LfgRolesMap &groles, bool removeLeaderFlag=true)
Checks if given roles match, modifies given roles map with new roles.
Definition: LFGMgr.cpp:1510
void AddToCompatibles(Lfg5Guids const &key)
Definition: LFGQueue.cpp:170
void UpdateBestCompatibleInQueue(LfgQueueDataContainer::iterator itrQueue, Lfg5Guids const &key)
Definition: LFGQueue.cpp:587
void RemoveFromQueue(ObjectGuid guid, bool partial=false)
Definition: LFGQueue.cpp:50
Definition: ObjectGuid.h:120
static ObjectGuid const Empty
Definition: ObjectGuid.h:122
Definition: Player.h:1046
Definition: InstanceScript.h:140
Definition: DBCStructure.h:1224

References lfg::LfgProposalPlayer::accept, lfg::Lfg5Guids::addRoles(), AddToCompatibles(), lfg::LfgProposal::cancelTime, lfg::LFGMgr::CheckGroupRoles(), ObjectGuid::Clear(), lfg::LfgProposal::dungeonId, lfg::LfgQueueData::dungeons, ObjectGuid::Empty, lfg::LfgProposal::encounters, ObjectAccessor::FindConnectedPlayer(), lfg::Lfg5Guids::force_insert_front(), lfg::Lfg5Guids::front(), GameTime::GetGameTime(), lfg::LfgProposalPlayer::group, lfg::LfgProposal::group, lfg::Lfg5Guids::guids, lfg::Lfg5Guids::insert(), lfg::LfgProposal::isNew, lfg::LfgProposal::leader, lfg::LFG_ANSWER_AGREE, lfg::LFG_COMPATIBILITY_PENDING, lfg::LFG_COMPATIBLES_MATCH, lfg::LFG_COMPATIBLES_WITH_LESS_PLAYERS, lfg::LFG_INCOMPATIBLES_HAS_IGNORES, lfg::LFG_INCOMPATIBLES_MULTIPLE_LFG_GROUPS, lfg::LFG_INCOMPATIBLES_NO_DUNGEONS, lfg::LFG_INCOMPATIBLES_NO_ROLES, lfg::LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS, lfg::LFG_PROPOSAL_INITIATING, lfg::LFG_TIME_PROPOSAL, LOG_DEBUG, LOG_ERROR, MAXGROUPSIZE, lfg::PLAYER_ROLE_LEADER, lfg::LfgProposal::players, QueueDataStore, lfg::LfgProposal::queues, RemoveFromQueue(), lfg::LfgProposalPlayer::role, lfg::LfgQueueData::roles, Acore::Containers::SelectRandomContainerElement(), lfg::Lfg5Guids::size(), sLFGDungeonStore, sLFGMgr, lfg::LfgProposal::state, lfg::Lfg5Guids::toString(), ObjectGuid::ToString(), UpdateBestCompatibleInQueue(), and urand().

Referenced by FindNewGroups().

◆ FindBestCompatibleInQueue()

uint32 lfg::LFGQueue::FindBestCompatibleInQueue ( LfgQueueDataContainer::iterator  itrQueue)
private
576 {
577 uint32 numOfCompatibles = 0;
578 for (LfgCompatibleContainer::const_iterator itr = CompatibleList.begin(); itr != CompatibleList.end(); ++itr)
579 if (itr->hasGuid(itrQueue->first))
580 {
581 ++numOfCompatibles;
582 UpdateBestCompatibleInQueue(itrQueue, *itr);
583 }
584 return numOfCompatibles;
585 }
LfgCompatibleContainer CompatibleList
Definition: LFGQueue.h:114

References CompatibleList, and UpdateBestCompatibleInQueue().

Referenced by UpdateQueueTimers().

◆ FindGroups()

uint8 lfg::LFGQueue::FindGroups ( )
177 {
178 LOG_DEBUG("lfg", "FIND GROUPS!");
179 uint8 newGroupsProcessed = 0;
180 if (!newToQueueStore.empty())
181 {
182 ++newGroupsProcessed;
183 ObjectGuid newGuid = newToQueueStore.front();
184 bool pushCompatiblesToFront = (std::find(restoredAfterProposal.begin(), restoredAfterProposal.end(), newGuid) != restoredAfterProposal.end());
185 LOG_DEBUG("lfg", "newToQueueStore: {}, front: {}", newGuid.ToString(), pushCompatiblesToFront ? 1 : 0);
186 RemoveFromNewQueue(newGuid);
187
188 FindNewGroups(newGuid);
189
190 CompatibleList.splice((pushCompatiblesToFront ? CompatibleList.begin() : CompatibleList.end()), CompatibleTempList);
191 CompatibleTempList.clear();
192
193 return newGroupsProcessed; // pussywizard: only one per update, shouldn't be a problem
194 }
195 return newGroupsProcessed;
196 }
void RemoveFromNewQueue(ObjectGuid guid)
Definition: LFGQueue.cpp:100
LfgCompatibility FindNewGroups(const ObjectGuid &newGuid)
Definition: LFGQueue.cpp:198

References CompatibleList, CompatibleTempList, FindNewGroups(), LOG_DEBUG, newToQueueStore, RemoveFromNewQueue(), restoredAfterProposal, and ObjectGuid::ToString().

◆ FindNewGroups()

LfgCompatibility lfg::LFGQueue::FindNewGroups ( const ObjectGuid newGuid)
private
199 {
200 // each combination of dps+heal+tank (tank*8 + heal+4 + dps) has a value assigned 0..15
201 // first 16 bits of the mask are for marking if such combination was found once, second 16 bits for marking second occurence of that combination, etc
202 uint64 foundMask = 0;
203 uint32 foundCount = 0;
204
205 LOG_DEBUG("lfg", "FIND NEW GROUPS for: {}", newGuid.ToString());
206
207 // we have to take into account that FindNewGroups is called every X minutes if number of compatibles is low!
208 // build set of already present compatibles for this guid
209 std::set<Lfg5Guids> currentCompatibles;
210 for (Lfg5GuidsList::iterator it = CompatibleList.begin(); it != CompatibleList.end(); ++it)
211 if (it->hasGuid(newGuid))
212 {
213 // unset roles here so they are not copied, restore after insertion
214 LfgRolesMap* r = it->roles;
215 it->roles = nullptr;
216 currentCompatibles.insert(*it);
217 it->roles = r;
218 }
219
221 if (currentCompatibles.empty())
222 {
223 selfCompatibility = CheckCompatibility(Lfg5Guids(), newGuid, foundMask, foundCount, currentCompatibles);
224 if (selfCompatibility != LFG_COMPATIBLES_WITH_LESS_PLAYERS) // group is already compatible (a party of 5 players)
225 return selfCompatibility;
226 }
227
228 for (Lfg5GuidsList::iterator it = CompatibleList.begin(); it != CompatibleList.end(); )
229 {
230 Lfg5GuidsList::iterator itr = it++;
231 if (itr->empty())
232 {
233 LOG_DEBUG("lfg", "ERASE from CompatibleList");
234 CompatibleList.erase(itr);
235 continue;
236 }
237 LfgCompatibility compatibility = CheckCompatibility(*itr, newGuid, foundMask, foundCount, currentCompatibles);
238 if (compatibility == LFG_COMPATIBLES_MATCH)
240 if ((foundMask & 0x3FFF3FFF3FFF3FFF) == 0x3FFF3FFF3FFF3FFF) // each combination of dps+heal+tank already found 4 times
241 break;
242 }
243
244 return selfCompatibility;
245 }
LfgCompatibility
Definition: LFGQueue.h:28
LfgCompatibility CheckCompatibility(Lfg5Guids const &checkWith, const ObjectGuid &newGuid, uint64 &foundMask, uint32 &foundCount, const std::set< Lfg5Guids > &currentCompatibles)
Definition: LFGQueue.cpp:247

References CheckCompatibility(), CompatibleList, lfg::LFG_COMPATIBILITY_PENDING, lfg::LFG_COMPATIBLES_MATCH, lfg::LFG_COMPATIBLES_WITH_LESS_PLAYERS, LOG_DEBUG, and ObjectGuid::ToString().

Referenced by FindGroups().

◆ GetJoinTime()

time_t lfg::LFGQueue::GetJoinTime ( ObjectGuid  guid)
571 {
572 return QueueDataStore[guid].joinTime;
573 }

References QueueDataStore.

Referenced by lfg::LFGMgr::UpdateProposal().

◆ RemoveFromCompatibles()

void lfg::LFGQueue::RemoveFromCompatibles ( ObjectGuid  guid)
private
151 {
152 LOG_DEBUG("lfg", "COMPATIBLES REMOVE for: {}", guid.ToString());
153 for (LfgCompatibleContainer::iterator it = CompatibleList.begin(); it != CompatibleList.end(); ++it)
154 if (it->hasGuid(guid))
155 {
156 LOG_DEBUG("lfg", "Removed Compatible: {}, because of: {}", it->toString(), guid.ToString());
157 it->clear(); // set to 0, this will be removed while iterating in FindNewGroups
158 }
159 for (LfgCompatibleContainer::iterator itr = CompatibleTempList.begin(); itr != CompatibleTempList.end(); )
160 {
161 LfgCompatibleContainer::iterator it = itr++;
162 if (it->hasGuid(guid))
163 {
164 LOG_DEBUG("lfg", "Erased Temp Compatible: {}, because of: {}", it->toString(), guid.ToString());
165 CompatibleTempList.erase(it);
166 }
167 }
168 }

References CompatibleList, CompatibleTempList, LOG_DEBUG, and ObjectGuid::ToString().

Referenced by RemoveFromQueue().

◆ RemoveFromNewQueue()

void lfg::LFGQueue::RemoveFromNewQueue ( ObjectGuid  guid)
private
101 {
102 LOG_DEBUG("lfg", "REMOVE RemoveFromNewQueue: {}", guid.ToString());
103 newToQueueStore.remove(guid);
104 restoredAfterProposal.remove(guid);
105 }

References LOG_DEBUG, newToQueueStore, restoredAfterProposal, and ObjectGuid::ToString().

Referenced by FindGroups(), and RemoveFromQueue().

◆ RemoveFromQueue()

void lfg::LFGQueue::RemoveFromQueue ( ObjectGuid  guid,
bool  partial = false 
)
51 {
52 LOG_DEBUG("lfg", "REMOVE RemoveFromQueue: {}, partial: {}", guid.ToString(), partial ? 1 : 0);
55
56 LfgQueueDataContainer::iterator itDelete = QueueDataStore.end();
57 for (LfgQueueDataContainer::iterator itr = QueueDataStore.begin(); itr != QueueDataStore.end(); ++itr)
58 {
59 if (itr->first != guid)
60 {
61 if (itr->second.bestCompatible.hasGuid(guid))
62 {
63 LOG_DEBUG("lfg", "CLEAR bestCompatible: {}, because of: {}", itr->second.bestCompatible.toString(), guid.ToString());
64 itr->second.bestCompatible.clear();
65 }
66 }
67 else
68 {
69 LOG_DEBUG("lfg", "CLEAR bestCompatible SELF: {}, because of: {}", itr->second.bestCompatible.toString(), guid.ToString());
70 //itr->second.bestCompatible.clear(); // don't clear here, because UpdateQueueTimers will try to find with every diff update
71 itDelete = itr;
72 }
73 }
74
75 // xinef: partial
76 if (!partial && itDelete != QueueDataStore.end())
77 {
78 LOG_DEBUG("lfg", "ERASE QueueDataStore for: {}", guid.ToString());
79 LOG_DEBUG("lfg", "ERASE QueueDataStore for: {}, itDelete: {},{},{}", guid.ToString(), itDelete->second.dps, itDelete->second.healers, itDelete->second.tanks);
80 QueueDataStore.erase(itDelete);
81 LOG_DEBUG("lfg", "ERASE QueueDataStore for: {} SUCCESS", guid.ToString());
82 }
83 }
void RemoveFromCompatibles(ObjectGuid guid)
Definition: LFGQueue.cpp:150

References LOG_DEBUG, QueueDataStore, RemoveFromCompatibles(), RemoveFromNewQueue(), and ObjectGuid::ToString().

Referenced by lfg::LFGMgr::AllQueued(), CheckCompatibility(), lfg::LFGMgr::JoinLfg(), lfg::LFGMgr::LeaveLfg(), and lfg::LFGMgr::RemoveProposal().

◆ RemoveQueueData()

void lfg::LFGQueue::RemoveQueueData ( ObjectGuid  guid)
115 {
116 LOG_DEBUG("lfg", "LEFT RemoveQueueData: {}", guid.ToString());
117 LfgQueueDataContainer::iterator it = QueueDataStore.find(guid);
118 if (it != QueueDataStore.end())
119 QueueDataStore.erase(it);
120 }

References LOG_DEBUG, QueueDataStore, and ObjectGuid::ToString().

Referenced by lfg::LFGMgr::UpdateProposal().

◆ SetQueueUpdateData()

void lfg::LFGQueue::SetQueueUpdateData ( std::string const &  strGuids,
LfgRolesMap const &  proposalRoles 
)
private

◆ UpdateBestCompatibleInQueue()

void lfg::LFGQueue::UpdateBestCompatibleInQueue ( LfgQueueDataContainer::iterator  itrQueue,
Lfg5Guids const &  key 
)
private
588 {
589 LOG_DEBUG("lfg", "UpdateBestCompatibleInQueue: {}", key.toString());
590 LfgQueueData& queueData = itrQueue->second;
591
592 uint8 storedSize = queueData.bestCompatible.size();
593 uint8 size = key.size();
594
595 if (size <= storedSize)
596 return;
597
598 queueData.bestCompatible = key;
599 queueData.tanks = LFG_TANKS_NEEDED;
600 queueData.healers = LFG_HEALERS_NEEDED;
601 queueData.dps = LFG_DPS_NEEDED;
602 for (LfgRolesMap::const_iterator it = key.roles->begin(); it != key.roles->end(); ++it)
603 {
604 uint8 role = it->second;
605 if (role & PLAYER_ROLE_TANK)
606 --queueData.tanks;
607 else if (role & PLAYER_ROLE_HEALER)
608 --queueData.healers;
609 else
610 --queueData.dps;
611 }
612 }
@ LFG_HEALERS_NEEDED
Definition: LFG.h:36
@ LFG_TANKS_NEEDED
Definition: LFG.h:35
@ LFG_DPS_NEEDED
Definition: LFG.h:37
@ PLAYER_ROLE_TANK
Definition: LFG.h:44
@ PLAYER_ROLE_HEALER
Definition: LFG.h:45

References lfg::LfgQueueData::bestCompatible, lfg::LfgQueueData::dps, lfg::LfgQueueData::healers, lfg::LFG_DPS_NEEDED, lfg::LFG_HEALERS_NEEDED, lfg::LFG_TANKS_NEEDED, LOG_DEBUG, lfg::PLAYER_ROLE_HEALER, lfg::PLAYER_ROLE_TANK, lfg::Lfg5Guids::roles, lfg::Lfg5Guids::size(), lfg::LfgQueueData::tanks, and lfg::Lfg5Guids::toString().

Referenced by CheckCompatibility(), and FindBestCompatibleInQueue().

◆ UpdateQueueTimers()

void lfg::LFGQueue::UpdateQueueTimers ( uint32  diff)
471 {
472 time_t currTime = GameTime::GetGameTime().count();
473 bool sendQueueStatus = false;
474
476 {
478 sendQueueStatus = true;
479 }
480 else
481 m_QueueStatusTimer += diff;
482
483 LOG_DEBUG("lfg", "UPDATE UpdateQueueTimers");
484 for (Lfg5GuidsList::iterator it = CompatibleList.begin(); it != CompatibleList.end(); )
485 {
486 Lfg5GuidsList::iterator itr = it++;
487 if (itr->empty())
488 {
489 LOG_DEBUG("lfg", "UpdateQueueTimers ERASE compatible");
490 CompatibleList.erase(itr);
491 }
492 }
493
494 if (!sendQueueStatus)
495 {
496 for (LfgQueueDataContainer::iterator itQueue = QueueDataStore.begin(); itQueue != QueueDataStore.end(); )
497 {
498 if (currTime - itQueue->second.joinTime > 2 * HOUR)
499 {
500 ObjectGuid guid = itQueue->first;
501 QueueDataStore.erase(itQueue++);
502 sLFGMgr->LeaveAllLfgQueues(guid, true);
503 continue;
504 }
505 if (itQueue->second.bestCompatible.empty())
506 {
507 uint32 numOfCompatibles = FindBestCompatibleInQueue(itQueue);
508 if (numOfCompatibles /*must be positive, because proposals don't delete QueueQueueData*/ && currTime - itQueue->second.lastRefreshTime >= 60 && numOfCompatibles < (5 - itQueue->second.bestCompatible.roles->size()) * 25)
509 {
510 itQueue->second.lastRefreshTime = currTime;
511 AddToQueue(itQueue->first, false);
512 }
513 }
514 ++itQueue;
515 }
516 return;
517 }
518
519 // LOG_TRACE("lfg", "Updating queue timers...");
520 for (LfgQueueDataContainer::iterator itQueue = QueueDataStore.begin(); itQueue != QueueDataStore.end(); ++itQueue)
521 {
522 LfgQueueData& queueinfo = itQueue->second;
523 uint32 dungeonId = (*queueinfo.dungeons.begin());
524 uint32 queuedTime = uint32(currTime - queueinfo.joinTime);
525 uint8 role = PLAYER_ROLE_NONE;
526 int32 waitTime = -1;
527 int32 wtTank = waitTimesTankStore[dungeonId].time;
528 int32 wtHealer = waitTimesHealerStore[dungeonId].time;
529 int32 wtDps = waitTimesDpsStore[dungeonId].time;
530 int32 wtAvg = waitTimesAvgStore[dungeonId].time;
531
532 for (LfgRolesMap::const_iterator itPlayer = queueinfo.roles.begin(); itPlayer != queueinfo.roles.end(); ++itPlayer)
533 role |= itPlayer->second;
534 role &= ~PLAYER_ROLE_LEADER;
535
536 switch (role)
537 {
538 case PLAYER_ROLE_NONE: // Should not happen - just in case
539 waitTime = -1;
540 break;
541 case PLAYER_ROLE_TANK:
542 waitTime = wtTank;
543 break;
545 waitTime = wtHealer;
546 break;
548 waitTime = wtDps;
549 break;
550 default:
551 waitTime = wtAvg;
552 break;
553 }
554
555 if (queueinfo.bestCompatible.empty())
556 {
557 LOG_DEBUG("lfg", "found empty bestCompatible");
559 }
560
561 LfgQueueStatusData queueData(dungeonId, waitTime, wtAvg, wtTank, wtHealer, wtDps, queuedTime, queueinfo.tanks, queueinfo.healers, queueinfo.dps);
562 for (LfgRolesMap::const_iterator itPlayer = queueinfo.roles.begin(); itPlayer != queueinfo.roles.end(); ++itPlayer)
563 {
564 ObjectGuid pguid = itPlayer->first;
565 LFGMgr::SendLfgQueueStatus(pguid, queueData);
566 }
567 }
568 }
constexpr auto HOUR
Definition: Common.h:57
std::int32_t int32
Definition: Define.h:104
@ LFG_QUEUEUPDATE_INTERVAL
Definition: LFGMgr.h:51
@ PLAYER_ROLE_DAMAGE
Definition: LFG.h:46
@ PLAYER_ROLE_NONE
Definition: LFG.h:42
static void SendLfgQueueStatus(ObjectGuid guid, LfgQueueStatusData const &data)
Sends queue status to player.
Definition: LFGMgr.cpp:2668
LfgWaitTimesContainer waitTimesTankStore
Definition: LFGQueue.h:118
LfgWaitTimesContainer waitTimesAvgStore
Definition: LFGQueue.h:117
uint32 FindBestCompatibleInQueue(LfgQueueDataContainer::iterator itrQueue)
Definition: LFGQueue.cpp:575
LfgWaitTimesContainer waitTimesDpsStore
Definition: LFGQueue.h:120
uint32 m_QueueStatusTimer
Definition: LFGQueue.h:112
LfgWaitTimesContainer waitTimesHealerStore
Definition: LFGQueue.h:119

References AddToQueue(), lfg::LfgQueueData::bestCompatible, CompatibleList, lfg::LfgQueueData::dps, lfg::LfgQueueData::dungeons, lfg::Lfg5Guids::empty(), FindBestCompatibleInQueue(), GameTime::GetGameTime(), lfg::LfgQueueData::healers, HOUR, lfg::LfgQueueData::joinTime, lfg::LFG_QUEUEUPDATE_INTERVAL, LOG_DEBUG, m_QueueStatusTimer, lfg::PLAYER_ROLE_DAMAGE, lfg::PLAYER_ROLE_HEALER, lfg::PLAYER_ROLE_NONE, lfg::PLAYER_ROLE_TANK, QueueDataStore, lfg::LfgQueueData::roles, lfg::LFGMgr::SendLfgQueueStatus(), sLFGMgr, lfg::LfgQueueData::tanks, waitTimesAvgStore, waitTimesDpsStore, waitTimesHealerStore, and waitTimesTankStore.

◆ UpdateWaitTimeAvg()

void lfg::LFGQueue::UpdateWaitTimeAvg ( int32  waitTime,
uint32  dungeonId 
)
123 {
124 LfgWaitTime& wt = waitTimesAvgStore[dungeonId];
125 uint32 old_number = wt.number++;
126 wt.time = int32((wt.time * old_number + waitTime) / wt.number);
127 }

References lfg::LfgWaitTime::number, lfg::LfgWaitTime::time, and waitTimesAvgStore.

Referenced by lfg::LFGMgr::UpdateProposal().

◆ UpdateWaitTimeDps()

void lfg::LFGQueue::UpdateWaitTimeDps ( int32  waitTime,
uint32  dungeonId 
)
144 {
145 LfgWaitTime& wt = waitTimesDpsStore[dungeonId];
146 uint32 old_number = wt.number++;
147 wt.time = int32((wt.time * old_number + waitTime) / wt.number);
148 }

References lfg::LfgWaitTime::number, lfg::LfgWaitTime::time, and waitTimesDpsStore.

Referenced by lfg::LFGMgr::UpdateProposal().

◆ UpdateWaitTimeHealer()

void lfg::LFGQueue::UpdateWaitTimeHealer ( int32  waitTime,
uint32  dungeonId 
)
137 {
138 LfgWaitTime& wt = waitTimesHealerStore[dungeonId];
139 uint32 old_number = wt.number++;
140 wt.time = int32((wt.time * old_number + waitTime) / wt.number);
141 }

References lfg::LfgWaitTime::number, lfg::LfgWaitTime::time, and waitTimesHealerStore.

Referenced by lfg::LFGMgr::UpdateProposal().

◆ UpdateWaitTimeTank()

void lfg::LFGQueue::UpdateWaitTimeTank ( int32  waitTime,
uint32  dungeonId 
)
130 {
131 LfgWaitTime& wt = waitTimesTankStore[dungeonId];
132 uint32 old_number = wt.number++;
133 wt.time = int32((wt.time * old_number + waitTime) / wt.number);
134 }

References lfg::LfgWaitTime::number, lfg::LfgWaitTime::time, and waitTimesTankStore.

Referenced by lfg::LFGMgr::UpdateProposal().

Member Data Documentation

◆ CompatibleList

◆ CompatibleTempList

LfgCompatibleContainer lfg::LFGQueue::CompatibleTempList
private

◆ m_QueueStatusTimer

uint32 lfg::LFGQueue::m_QueueStatusTimer
private

Referenced by UpdateQueueTimers().

◆ newToQueueStore

LfgGuidList lfg::LFGQueue::newToQueueStore
private

◆ QueueDataStore

◆ restoredAfterProposal

LfgGuidList lfg::LFGQueue::restoredAfterProposal
private

◆ waitTimesAvgStore

LfgWaitTimesContainer lfg::LFGQueue::waitTimesAvgStore
private

◆ waitTimesDpsStore

LfgWaitTimesContainer lfg::LFGQueue::waitTimesDpsStore
private

◆ waitTimesHealerStore

LfgWaitTimesContainer lfg::LFGQueue::waitTimesHealerStore
private

◆ waitTimesTankStore

LfgWaitTimesContainer lfg::LFGQueue::waitTimesTankStore
private