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 
)
107 {
108 LOG_DEBUG("lfg", "JOINED AddQueueData: {}", guid.ToString());
109 QueueDataStore[guid] = LfgQueueData(joinTime, dungeons, rolesMap);
110 AddToQueue(guid);
111 }
#define LOG_DEBUG(filterType__,...)
Definition: Log.h:169
LfgQueueDataContainer QueueDataStore
Definition: LFGQueue.h:111
void AddToQueue(ObjectGuid guid, bool failedProposal=false)
Definition: LFGQueue.cpp:36
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
170 {
171 LOG_DEBUG("lfg", "COMPATIBLES ADD: {}", key.toString());
172 CompatibleTempList.push_back(key);
173 }
LfgCompatibleContainer CompatibleTempList
Definition: LFGQueue.h:113

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

Referenced by CheckCompatibility().

◆ AddToNewQueue()

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

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

Referenced by AddToQueue().

◆ AddToQueue()

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

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

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
575 {
576 uint32 numOfCompatibles = 0;
577 for (LfgCompatibleContainer::const_iterator itr = CompatibleList.begin(); itr != CompatibleList.end(); ++itr)
578 if (itr->hasGuid(itrQueue->first))
579 {
580 ++numOfCompatibles;
581 UpdateBestCompatibleInQueue(itrQueue, *itr);
582 }
583 return numOfCompatibles;
584 }
LfgCompatibleContainer CompatibleList
Definition: LFGQueue.h:112

References CompatibleList, and UpdateBestCompatibleInQueue().

Referenced by UpdateQueueTimers().

◆ FindGroups()

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

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

◆ FindNewGroups()

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

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)
570 {
571 return QueueDataStore[guid].joinTime;
572 }

References QueueDataStore.

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

◆ RemoveFromCompatibles()

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

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

Referenced by RemoveFromQueue().

◆ RemoveFromNewQueue()

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

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

Referenced by FindGroups(), and RemoveFromQueue().

◆ RemoveFromQueue()

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

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)
114 {
115 LOG_DEBUG("lfg", "LEFT RemoveQueueData: {}", guid.ToString());
116 LfgQueueDataContainer::iterator it = QueueDataStore.find(guid);
117 if (it != QueueDataStore.end())
118 QueueDataStore.erase(it);
119 }

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
587 {
588 LOG_DEBUG("lfg", "UpdateBestCompatibleInQueue: {}", key.toString());
589 LfgQueueData& queueData = itrQueue->second;
590
591 uint8 storedSize = queueData.bestCompatible.size();
592 uint8 size = key.size();
593
594 if (size <= storedSize)
595 return;
596
597 queueData.bestCompatible = key;
598 queueData.tanks = LFG_TANKS_NEEDED;
599 queueData.healers = LFG_HEALERS_NEEDED;
600 queueData.dps = LFG_DPS_NEEDED;
601 for (LfgRolesMap::const_iterator it = key.roles->begin(); it != key.roles->end(); ++it)
602 {
603 uint8 role = it->second;
604 if (role & PLAYER_ROLE_TANK)
605 --queueData.tanks;
606 else if (role & PLAYER_ROLE_HEALER)
607 --queueData.healers;
608 else
609 --queueData.dps;
610 }
611 }
@ LFG_HEALERS_NEEDED
Definition: LFG.h:33
@ LFG_TANKS_NEEDED
Definition: LFG.h:32
@ LFG_DPS_NEEDED
Definition: LFG.h:34
@ PLAYER_ROLE_TANK
Definition: LFG.h:41
@ PLAYER_ROLE_HEALER
Definition: LFG.h:42

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

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 
)
122 {
123 LfgWaitTime& wt = waitTimesAvgStore[dungeonId];
124 uint32 old_number = wt.number++;
125 wt.time = int32((wt.time * old_number + waitTime) / wt.number);
126 }

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

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

◆ UpdateWaitTimeDps()

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

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

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

◆ UpdateWaitTimeHealer()

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

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

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

◆ UpdateWaitTimeTank()

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

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