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 (ObjectGuid const &newGuid)
 
LfgCompatibility CheckCompatibility (Lfg5Guids const &checkWith, ObjectGuid const &newGuid, uint64 &foundMask, uint32 &foundCount, std::set< Lfg5Guids > const &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:157
std::string ToString() const
Definition ObjectGuid.cpp:48
LfgQueueDataContainer QueueDataStore
Definition LFGQueue.h:112
void AddToQueue(ObjectGuid guid, bool failedProposal=false)
Definition LFGQueue.cpp:37

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:114

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:121
LfgGuidList newToQueueStore
Definition LFGQueue.h:120

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:145
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,
ObjectGuid const &  newGuid,
uint64 &  foundMask,
uint32 &  foundCount,
std::set< Lfg5Guids > const &  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 LfgRolesMap const& 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 std::swap(proposalDungeons, temporal);
379 }
380
381 if (proposalDungeons.empty())
383 }
384 else
385 {
386 ObjectGuid gguid = check.front();
387 LfgQueueData const& 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 if (!sScriptMgr->CanCreateLfgProposal(proposal.queues))
417
418 // Create a new proposal
419 proposal.cancelTime = GameTime::GetGameTime().count() + LFG_TIME_PROPOSAL;
420 proposal.state = LFG_PROPOSAL_INITIATING;
421 proposal.leader.Clear();
422
423 // Filter out recently completed dungeons to prevent same dungeon in a row
424 LfgDungeonSet filteredDungeons = sLFGMgr->FilterCooldownDungeons(proposalDungeons, proposalRoles);
425 proposal.dungeonId = Acore::Containers::SelectRandomContainerElement(filteredDungeons);
426
427 uint32 completedEncounters = 0;
428 bool leader = false;
429 for (LfgRolesMap::const_iterator itRoles = proposalRoles.begin(); itRoles != proposalRoles.end(); ++itRoles)
430 {
431 // Assing new leader
432 if (itRoles->second & PLAYER_ROLE_LEADER)
433 {
434 if (!leader || !proposal.leader || urand(0, 1))
435 proposal.leader = itRoles->first;
436 leader = true;
437 }
438 else if (!leader && (!proposal.leader || urand(0, 1)))
439 proposal.leader = itRoles->first;
440
441 // Assing player data and roles
442 LfgProposalPlayer& data = proposal.players[itRoles->first];
443 data.role = itRoles->second;
444 data.group = proposalGroups.find(itRoles->first)->second;
445 if (!proposal.isNew && data.group && data.group == proposal.group) // Player from existing group, autoaccept
446 data.accept = LFG_ANSWER_AGREE;
447
448 if (!completedEncounters && !proposal.isNew)
449 {
450 if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(proposal.dungeonId))
451 {
452 if (Player* player = ObjectAccessor::FindConnectedPlayer(itRoles->first))
453 {
454 if (player->GetMapId() == static_cast<uint32>(dungeon->MapID))
455 {
456 if (InstanceScript* instance = player->GetInstanceScript())
457 {
458 completedEncounters = instance->GetCompletedEncounterMask();
459 }
460 }
461 }
462 }
463 }
464 }
465
466 proposal.encounters = completedEncounters;
467
468 for (uint8 i = 0; i < 5 && proposal.queues.guids[i]; ++i)
469 RemoveFromQueue(proposal.queues.guids[i], true);
470
471 sLFGMgr->AddProposal(proposal);
472
474 }
DBCStorage< LFGDungeonEntry > sLFGDungeonStore(LFGDungeonEntryfmt)
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:44
#define sLFGMgr
Definition LFGMgr.h:665
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:44
#define sScriptMgr
Definition ScriptMgr.h:766
Definition InstanceScript.h:143
Definition ObjectGuid.h:121
static ObjectGuid const Empty
Definition ObjectGuid.h:123
Definition Player.h:1086
static uint8 CheckGroupRoles(LfgRolesMap &groles)
Checks if given roles match, modifies given roles map with new roles.
Definition LFGMgr.cpp:1603
void AddToCompatibles(Lfg5Guids const &key)
Definition LFGQueue.cpp:170
void UpdateBestCompatibleInQueue(LfgQueueDataContainer::iterator itrQueue, Lfg5Guids const &key)
Definition LFGQueue.cpp:593
void RemoveFromQueue(ObjectGuid guid, bool partial=false)
Definition LFGQueue.cpp:50
auto SelectRandomContainerElement(C const &container) -> typename std::add_const< decltype(*std::begin(container))>::type &
Definition Containers.h:133
Seconds GetGameTime()
Definition GameTime.cpp:38
Player * FindConnectedPlayer(ObjectGuid const guid)
Definition ObjectAccessor.cpp:281
std::map< ObjectGuid, uint8 > LfgRolesMap
Definition LFG.h:119
@ LFG_TIME_PROPOSAL
Definition LFGMgr.h:51
@ LFG_ANSWER_AGREE
Definition LFG.h:100
@ LFG_COMPATIBLES_WITH_LESS_PLAYERS
Definition LFGQueue.h:35
@ 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:36
@ LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS
Definition LFGQueue.h:29
@ LFG_INCOMPATIBLES_NO_ROLES
Definition LFGQueue.h:32
@ LFG_INCOMPATIBLES_REJECTED_BY_SCRIPT
Definition LFGQueue.h:34
std::set< uint32 > LfgDungeonSet
Definition LFG.h:114
std::map< ObjectGuid, ObjectGuid > LfgGroupsMap
Definition LFG.h:120
@ PLAYER_ROLE_LEADER
Definition LFG.h:40
@ LFG_PROPOSAL_INITIATING
Definition LFGMgr.h:81
Definition DBCStructure.h:1281

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_REJECTED_BY_SCRIPT, 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, sScriptMgr, lfg::LfgProposal::state, lfg::Lfg5Guids::toString(), ObjectGuid::ToString(), UpdateBestCompatibleInQueue(), and urand().

Referenced by FindNewGroups().

◆ FindBestCompatibleInQueue()

uint32 lfg::LFGQueue::FindBestCompatibleInQueue ( LfgQueueDataContainer::iterator  itrQueue)
private
582 {
583 uint32 numOfCompatibles = 0;
584 for (LfgCompatibleContainer::const_iterator itr = CompatibleList.begin(); itr != CompatibleList.end(); ++itr)
585 if (itr->hasGuid(itrQueue->first))
586 {
587 ++numOfCompatibles;
588 UpdateBestCompatibleInQueue(itrQueue, *itr);
589 }
590 return numOfCompatibles;
591 }
LfgCompatibleContainer CompatibleList
Definition LFGQueue.h:113

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 }
LfgCompatibility FindNewGroups(ObjectGuid const &newGuid)
Definition LFGQueue.cpp:198
void RemoveFromNewQueue(ObjectGuid guid)
Definition LFGQueue.cpp:100

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

◆ FindNewGroups()

LfgCompatibility lfg::LFGQueue::FindNewGroups ( ObjectGuid const &  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 CheckCompatibility(Lfg5Guids const &checkWith, ObjectGuid const &newGuid, uint64 &foundMask, uint32 &foundCount, std::set< Lfg5Guids > const &currentCompatibles)
Definition LFGQueue.cpp:247
LfgCompatibility
Definition LFGQueue.h:26

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)
577 {
578 return QueueDataStore[guid].joinTime;
579 }

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

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

The documentation for this class was generated from the following files: