TrinityCore
Loading...
Searching...
No Matches
LFGQueue.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "ObjectDefines.h"
19#include "Containers.h"
20#include "DBCStructure.h"
21#include "DBCStores.h"
22#include "GameTime.h"
23#include "Group.h"
24#include "LFGQueue.h"
25#include "LFGMgr.h"
26#include "Log.h"
27
28namespace lfg
29{
30
37std::string ConcatenateGuids(GuidList const& check)
38{
39 if (check.empty())
40 return "";
41
42 // need the guids in order to avoid duplicates
43 GuidSet guids(check.begin(), check.end());
44
45 std::ostringstream o;
46
47 GuidSet::const_iterator it = guids.begin();
48 o << it->GetRawValue();
49 for (++it; it != guids.end(); ++it)
50 o << '|' << it->GetRawValue();
51
52 return o.str();
53}
54
55char const* GetCompatibleString(LfgCompatibility compatibles)
56{
57 switch (compatibles)
58 {
60 return "Pending";
62 return "Compatibles (Bad States)";
64 return "Match";
66 return "Compatibles (Not enough players)";
68 return "Has ignores";
70 return "Multiple Lfg Groups";
72 return "Incompatible dungeons";
74 return "Incompatible roles";
76 return "Too many players";
78 return "Wrong group size";
79 default:
80 return "Unknown";
81 }
82}
83
84LfgQueueData::LfgQueueData() : joinTime(GameTime::GetGameTime()), tanks(LFG_TANKS_NEEDED),
86{ }
87
88std::string LFGQueue::GetDetailedMatchRoles(GuidList const& check) const
89{
90 if (check.empty())
91 return "";
92
93 // need the guids in order to avoid duplicates
94 GuidSet guids(check.begin(), check.end());
95
96 std::ostringstream o;
97
98 GuidSet::const_iterator it = guids.begin();
99 o << it->GetRawValue();
100 LfgQueueDataContainer::const_iterator itQueue = QueueDataStore.find(*it);
101 if (itQueue != QueueDataStore.end())
102 {
103 // skip leader flag, log only dps/tank/healer
104 auto role = itQueue->second.roles.find(*it);
105 if (role != itQueue->second.roles.end())
106 o << ' ' << GetRolesString(itQueue->second.roles.at(*it) & uint8(~PLAYER_ROLE_LEADER));
107 }
108
109 for (++it; it != guids.end(); ++it)
110 {
111 o << '|' << it->GetRawValue();
112 itQueue = QueueDataStore.find(*it);
113 if (itQueue != QueueDataStore.end())
114 {
115 // skip leader flag, log only dps/tank/healer
116 auto role = itQueue->second.roles.find(*it);
117 if (role != itQueue->second.roles.end())
118 o << ' ' << GetRolesString(itQueue->second.roles.at(*it) & uint8(~PLAYER_ROLE_LEADER));
119 }
120 }
121
122 return o.str();
123}
124
125void LFGQueue::AddToQueue(ObjectGuid guid, bool reAdd)
126{
127 LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(guid);
128 if (itQueue == QueueDataStore.end())
129 {
130 TC_LOG_ERROR("lfg.queue.add", "Queue data not found for [{}]", guid.ToString());
131 return;
132 }
133
134 if (reAdd)
136 else
137 AddToNewQueue(guid);
138}
139
141{
142 RemoveFromNewQueue(guid);
145
146 std::ostringstream o;
147 o << guid.GetRawValue();
148 std::string sguid = o.str();
149
150 LfgQueueDataContainer::iterator itDelete = QueueDataStore.end();
151 for (LfgQueueDataContainer::iterator itr = QueueDataStore.begin(); itr != QueueDataStore.end(); ++itr)
152 if (itr->first != guid)
153 {
154 if (std::string::npos != itr->second.bestCompatible.find(sguid))
155 {
156 itr->second.bestCompatible.clear();
158 }
159 }
160 else
161 itDelete = itr;
162
163 if (itDelete != QueueDataStore.end())
164 QueueDataStore.erase(itDelete);
165}
166
168{
169 newToQueueStore.push_back(guid);
170}
171
173{
174 newToQueueStore.remove(guid);
175}
176
178{
179 currentQueueStore.push_back(guid);
180}
181
183{
184 currentQueueStore.push_front(guid);
185}
186
188{
189 currentQueueStore.remove(guid);
190}
191
192void LFGQueue::AddQueueData(ObjectGuid guid, time_t joinTime, LfgDungeonSet const& dungeons, LfgRolesMap const& rolesMap)
193{
194 QueueDataStore[guid] = LfgQueueData(joinTime, dungeons, rolesMap);
195 AddToQueue(guid);
196}
197
199{
200 LfgQueueDataContainer::iterator it = QueueDataStore.find(guid);
201 if (it != QueueDataStore.end())
202 QueueDataStore.erase(it);
203}
204
205void LFGQueue::UpdateWaitTimeAvg(int32 waitTime, uint32 dungeonId)
206{
207 LfgWaitTime &wt = waitTimesAvgStore[dungeonId];
208 uint32 old_number = wt.number++;
209 wt.time = int32((wt.time * old_number + waitTime) / wt.number);
210}
211
213{
214 LfgWaitTime &wt = waitTimesTankStore[dungeonId];
215 uint32 old_number = wt.number++;
216 wt.time = int32((wt.time * old_number + waitTime) / wt.number);
217}
218
220{
221 LfgWaitTime &wt = waitTimesHealerStore[dungeonId];
222 uint32 old_number = wt.number++;
223 wt.time = int32((wt.time * old_number + waitTime) / wt.number);
224}
225
226void LFGQueue::UpdateWaitTimeDps(int32 waitTime, uint32 dungeonId)
227{
228 LfgWaitTime &wt = waitTimesDpsStore[dungeonId];
229 uint32 old_number = wt.number++;
230 wt.time = int32((wt.time * old_number + waitTime) / wt.number);
231}
232
239{
240 std::stringstream out;
241 out << guid.GetRawValue();
242 std::string strGuid = out.str();
243
244 TC_LOG_DEBUG("lfg.queue.data.compatibles.remove", "Removing {}", guid.ToString());
245 for (LfgCompatibleContainer::iterator itNext = CompatibleMapStore.begin(); itNext != CompatibleMapStore.end();)
246 {
247 LfgCompatibleContainer::iterator it = itNext++;
248 if (std::string::npos != it->first.find(strGuid))
249 CompatibleMapStore.erase(it);
250 }
251}
252
259void LFGQueue::SetCompatibles(std::string const& key, LfgCompatibility compatibles)
260{
262 data.compatibility = compatibles;
263}
264
265void LFGQueue::SetCompatibilityData(std::string const& key, LfgCompatibilityData const& data)
266{
267 CompatibleMapStore[key] = data;
268}
269
277{
278 LfgCompatibleContainer::iterator itr = CompatibleMapStore.find(key);
279 if (itr != CompatibleMapStore.end())
280 return itr->second.compatibility;
281
283}
284
286{
287 LfgCompatibleContainer::iterator itr = CompatibleMapStore.find(key);
288 if (itr != CompatibleMapStore.end())
289 return &(itr->second);
290
291 return nullptr;
292}
293
295{
296 uint8 proposals = 0;
297 GuidList firstNew;
298 while (!newToQueueStore.empty())
299 {
300 ObjectGuid frontguid = newToQueueStore.front();
301 TC_LOG_DEBUG("lfg.queue.match.check.new", "Checking [{}] newToQueue({}), currentQueue({})", frontguid.ToString(),
303
304 firstNew.clear();
305 firstNew.push_back(frontguid);
306 RemoveFromNewQueue(frontguid);
307
308 GuidList temporalList = currentQueueStore;
309 LfgCompatibility compatibles = FindNewGroups(firstNew, temporalList);
310
311 if (compatibles == LFG_COMPATIBLES_MATCH)
312 ++proposals;
313 else
314 AddToCurrentQueue(frontguid); // Lfg group not found, add this group to the queue.
315 }
316 return proposals;
317}
318
327{
328 std::string strGuids = ConcatenateGuids(check);
329 LfgCompatibility compatibles = GetCompatibles(strGuids);
330
331 TC_LOG_DEBUG("lfg.queue.match.check", "Guids: ({}): {} - all({})", GetDetailedMatchRoles(check), GetCompatibleString(compatibles), GetDetailedMatchRoles(all));
332 if (compatibles == LFG_COMPATIBILITY_PENDING) // Not previously cached, calculate
333 compatibles = CheckCompatibility(check);
334
335 if (compatibles == LFG_COMPATIBLES_BAD_STATES && sLFGMgr->AllQueued(check))
336 {
337 TC_LOG_DEBUG("lfg.queue.match.check", "Guids: ({}) compatibles (cached) changed from bad states to match", GetDetailedMatchRoles(check));
340 }
341
342 if (compatibles != LFG_COMPATIBLES_WITH_LESS_PLAYERS)
343 return compatibles;
344
345 // Try to match with queued groups
346 while (!all.empty())
347 {
348 check.push_back(all.front());
349 all.pop_front();
350 LfgCompatibility subcompatibility = FindNewGroups(check, all);
351 if (subcompatibility == LFG_COMPATIBLES_MATCH)
353 check.pop_back();
354 }
355 return compatibles;
356}
357
365{
366 std::string strGuids = ConcatenateGuids(check);
367 LfgProposal proposal;
368 LfgDungeonSet proposalDungeons;
369 LfgGroupsMap proposalGroups;
370 LfgRolesMap proposalRoles;
371
372 // Check for correct size
373 if (check.size() > MAX_GROUP_SIZE || check.empty())
374 {
375 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}): Size wrong - Not compatibles", GetDetailedMatchRoles(check));
377 }
378
379 // Check all-but-new compatiblitity
380 if (check.size() > 2)
381 {
382 ObjectGuid frontGuid = check.front();
383 check.pop_front();
384
385 // Check all-but-new compatibilities (New, A, B, C, D) --> check(A, B, C, D)
386 LfgCompatibility child_compatibles = CheckCompatibility(check);
387 if (child_compatibles < LFG_COMPATIBLES_WITH_LESS_PLAYERS) // Group not compatible
388 {
389 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}) child {} not compatibles", strGuids, GetDetailedMatchRoles(check));
390 SetCompatibles(strGuids, child_compatibles);
391 return child_compatibles;
392 }
393 check.push_front(frontGuid);
394 }
395
396 // Check if more than one LFG group and number of players joining
397 uint8 numPlayers = 0;
398 uint8 numLfgGroups = 0;
399 for (GuidList::const_iterator it = check.begin(); it != check.end() && numLfgGroups < 2 && numPlayers <= MAX_GROUP_SIZE; ++it)
400 {
401 ObjectGuid guid = *it;
402 LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(guid);
403 if (itQueue == QueueDataStore.end())
404 {
405 TC_LOG_ERROR("lfg.queue.match.compatibility.check", "Guid: [{}] is not queued but listed as queued!", guid.ToString());
406 RemoveFromQueue(guid);
408 }
409
410 // 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)
411 for (LfgRolesMap::const_iterator it2 = itQueue->second.roles.begin(); it2 != itQueue->second.roles.end(); ++it2)
412 proposalGroups[it2->first] = itQueue->first.IsGroup() ? itQueue->first : ObjectGuid::Empty;
413
414 numPlayers += itQueue->second.roles.size();
415
416 if (sLFGMgr->IsLfgGroup(guid))
417 {
418 if (!numLfgGroups)
419 proposal.group = guid;
420 ++numLfgGroups;
421 }
422 }
423
424 // Group with less that MAX_GROUP_SIZE members always compatible
425 if (check.size() == 1 && numPlayers != MAX_GROUP_SIZE)
426 {
427 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}) single group. Compatibles", GetDetailedMatchRoles(check));
428 LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(check.front());
429
431 data.roles = itQueue->second.roles;
433
434 UpdateBestCompatibleInQueue(itQueue, strGuids, data.roles);
435 SetCompatibilityData(strGuids, data);
437 }
438
439 if (numLfgGroups > 1)
440 {
441 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}) More than one Lfggroup ({})", GetDetailedMatchRoles(check), numLfgGroups);
444 }
445
446 if (numPlayers > MAX_GROUP_SIZE)
447 {
448 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}) Too many players ({})", GetDetailedMatchRoles(check), numPlayers);
451 }
452
453 // 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
454 if (check.size() > 1)
455 {
456 for (GuidList::const_iterator it = check.begin(); it != check.end(); ++it)
457 {
458 LfgRolesMap const& roles = QueueDataStore[(*it)].roles;
459 for (LfgRolesMap::const_iterator itRoles = roles.begin(); itRoles != roles.end(); ++itRoles)
460 {
461 LfgRolesMap::const_iterator itPlayer;
462 for (itPlayer = proposalRoles.begin(); itPlayer != proposalRoles.end(); ++itPlayer)
463 {
464 if (itRoles->first == itPlayer->first)
465 TC_LOG_ERROR("lfg.queue.match.compatibility.check", "Guids: ERROR! Player multiple times in queue! [{}]", itRoles->first.ToString());
466 else if (sLFGMgr->HasIgnore(itRoles->first, itPlayer->first))
467 break;
468 }
469 if (itPlayer == proposalRoles.end())
470 proposalRoles[itRoles->first] = itRoles->second;
471 }
472 }
473
474 if (uint8 playersize = numPlayers - proposalRoles.size())
475 {
476 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}) not compatible, {} players are ignoring each other", GetDetailedMatchRoles(check), playersize);
479 }
480
481 LfgRolesMap debugRoles = proposalRoles;
482 if (!LFGMgr::CheckGroupRoles(proposalRoles))
483 {
484 std::ostringstream o;
485 for (LfgRolesMap::const_iterator it = debugRoles.begin(); it != debugRoles.end(); ++it)
486 o << ", " << it->first.GetRawValue() << ": " << GetRolesString(it->second);
487
488 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}) Roles not compatible{}", GetDetailedMatchRoles(check), o.str());
491 }
492
493 GuidList::iterator itguid = check.begin();
494 proposalDungeons = QueueDataStore[*itguid].dungeons;
495 std::ostringstream o;
496 o << ", " << itguid->GetRawValue() << ": (" << ConcatenateDungeons(proposalDungeons) << ")";
497 for (++itguid; itguid != check.end(); ++itguid)
498 {
499 LfgDungeonSet temporal;
500 LfgDungeonSet& dungeons = QueueDataStore[*itguid].dungeons;
501 o << ", " << itguid->GetRawValue() << ": (" << ConcatenateDungeons(dungeons) << ")";
502 std::set_intersection(proposalDungeons.begin(), proposalDungeons.end(), dungeons.begin(), dungeons.end(), std::inserter(temporal, temporal.begin()));
503 proposalDungeons = temporal;
504 }
505
506 if (proposalDungeons.empty())
507 {
508 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}) No compatible dungeons{}", GetDetailedMatchRoles(check), o.str());
511 }
512 }
513 else
514 {
515 ObjectGuid gguid = *check.begin();
516 LfgQueueData const& queue = QueueDataStore[gguid];
517 proposalDungeons = queue.dungeons;
518 proposalRoles = queue.roles;
519 LFGMgr::CheckGroupRoles(proposalRoles); // assing new roles
520 }
521
522 // Enough players?
523 if (numPlayers != MAX_GROUP_SIZE)
524 {
525 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}) Compatibles but not enough players({})", GetDetailedMatchRoles(check), numPlayers);
527 data.roles = proposalRoles;
528
529 for (GuidList::const_iterator itr = check.begin(); itr != check.end(); ++itr)
530 UpdateBestCompatibleInQueue(QueueDataStore.find(*itr), strGuids, data.roles);
531
532 SetCompatibilityData(strGuids, data);
534 }
535
536 ObjectGuid gguid = *check.begin();
537 proposal.queues = check;
538 proposal.isNew = numLfgGroups != 1 || sLFGMgr->GetOldState(gguid) != LFG_STATE_DUNGEON;
539
540 if (!sLFGMgr->AllQueued(check))
541 {
542 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}) Group MATCH but can't create proposal!", GetDetailedMatchRoles(check));
545 }
546
547 // Create a new proposal
550 proposal.leader.Clear();
552
553 bool leader = false;
554 for (LfgRolesMap::const_iterator itRoles = proposalRoles.begin(); itRoles != proposalRoles.end(); ++itRoles)
555 {
556 // Assing new leader
557 if (itRoles->second & PLAYER_ROLE_LEADER)
558 {
559 if (!leader || !proposal.leader || urand(0, 1))
560 proposal.leader = itRoles->first;
561 leader = true;
562 }
563 else if (!leader && (!proposal.leader || urand(0, 1)))
564 proposal.leader = itRoles->first;
565
566 // Assing player data and roles
567 LfgProposalPlayer &data = proposal.players[itRoles->first];
568 data.role = itRoles->second;
569 data.group = proposalGroups.find(itRoles->first)->second;
570 if (!proposal.isNew && !data.group.IsEmpty() && data.group == proposal.group) // Player from existing group, autoaccept
572 }
573
574 // Mark proposal members as not queued (but not remove queue data)
575 for (GuidList::const_iterator itQueue = proposal.queues.begin(); itQueue != proposal.queues.end(); ++itQueue)
576 {
577 ObjectGuid guid = (*itQueue);
578 RemoveFromNewQueue(guid);
580 }
581
582 sLFGMgr->AddProposal(proposal);
583
584 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}) MATCH! Group formed", GetDetailedMatchRoles(check));
587}
588
589void LFGQueue::UpdateQueueTimers(time_t currTime)
590{
591 TC_LOG_TRACE("lfg.queue.timers.update", "Updating queue timers...");
592 for (LfgQueueDataContainer::iterator itQueue = QueueDataStore.begin(); itQueue != QueueDataStore.end(); ++itQueue)
593 {
594 LfgQueueData& queueinfo = itQueue->second;
595 uint32 dungeonId = (*queueinfo.dungeons.begin());
596 uint32 queuedTime = uint32(currTime - queueinfo.joinTime);
597 uint8 role = PLAYER_ROLE_NONE;
598 int32 waitTime = -1;
599 int32 wtTank = waitTimesTankStore[dungeonId].time;
600 int32 wtHealer = waitTimesHealerStore[dungeonId].time;
601 int32 wtDps = waitTimesDpsStore[dungeonId].time;
602 int32 wtAvg = waitTimesAvgStore[dungeonId].time;
603
604 for (LfgRolesMap::const_iterator itPlayer = queueinfo.roles.begin(); itPlayer != queueinfo.roles.end(); ++itPlayer)
605 role |= itPlayer->second;
606 role &= ~PLAYER_ROLE_LEADER;
607
608 switch (role)
609 {
610 case PLAYER_ROLE_NONE: // Should not happen - just in case
611 waitTime = -1;
612 break;
613 case PLAYER_ROLE_TANK:
614 waitTime = wtTank;
615 break;
617 waitTime = wtHealer;
618 break;
620 waitTime = wtDps;
621 break;
622 default:
623 waitTime = wtAvg;
624 break;
625 }
626
627 if (queueinfo.bestCompatible.empty())
629
630 LfgQueueStatusData queueData(dungeonId, waitTime, wtAvg, wtTank, wtHealer, wtDps, queuedTime, queueinfo.tanks, queueinfo.healers, queueinfo.dps);
631 for (LfgRolesMap::const_iterator itPlayer = queueinfo.roles.begin(); itPlayer != queueinfo.roles.end(); ++itPlayer)
632 {
633 ObjectGuid pguid = itPlayer->first;
634 LFGMgr::SendLfgQueueStatus(pguid, queueData);
635 }
636 }
637}
638
640{
641 LfgQueueDataContainer::const_iterator itr = QueueDataStore.find(guid);
642 if (itr != QueueDataStore.end())
643 return itr->second.joinTime;
644
645 return 0;
646}
647
648std::string LFGQueue::DumpQueueInfo() const
649{
650 uint32 players = 0;
651 uint32 groups = 0;
652 uint32 playersInGroup = 0;
653
654 for (uint8 i = 0; i < 2; ++i)
655 {
656 GuidList const& queue = i ? newToQueueStore : currentQueueStore;
657 for (GuidList::const_iterator it = queue.begin(); it != queue.end(); ++it)
658 {
659 ObjectGuid guid = *it;
660 if (guid.IsGroup())
661 {
662 groups++;
663 playersInGroup += sLFGMgr->GetPlayerCount(guid);
664 }
665 else
666 players++;
667 }
668 }
669 std::ostringstream o;
670 o << "Queued Players: " << players << " (in group: " << playersInGroup << ") Groups: " << groups << "\n";
671 return o.str();
672}
673
674std::string LFGQueue::DumpCompatibleInfo(bool full /* = false */) const
675{
676 std::ostringstream o;
677 o << "Compatible Map size: " << CompatibleMapStore.size() << "\n";
678 if (full)
679 for (LfgCompatibleContainer::const_iterator itr = CompatibleMapStore.begin(); itr != CompatibleMapStore.end(); ++itr)
680 {
681 o << "(" << itr->first << "): " << GetCompatibleString(itr->second.compatibility);
682 if (!itr->second.roles.empty())
683 {
684 o << " (";
685 bool first = true;
686 for (auto const& role : itr->second.roles)
687 {
688 if (!first)
689 o << "|";
690 o << role.first.GetRawValue() << " " << GetRolesString(role.second & uint8(~PLAYER_ROLE_LEADER));
691 first = false;
692 }
693 o << ")";
694 }
695 o << "\n";
696 }
697
698 return o.str();
699}
700
701void LFGQueue::FindBestCompatibleInQueue(LfgQueueDataContainer::iterator itrQueue)
702{
703 TC_LOG_DEBUG("lfg.queue.compatibles.find", "{}", itrQueue->first.ToString());
704 std::ostringstream o;
705 o << itrQueue->first.GetRawValue();
706 std::string sguid = o.str();
707
708 for (LfgCompatibleContainer::const_iterator itr = CompatibleMapStore.begin(); itr != CompatibleMapStore.end(); ++itr)
709 if (itr->second.compatibility == LFG_COMPATIBLES_WITH_LESS_PLAYERS &&
710 std::string::npos != itr->first.find(sguid))
711 {
712 UpdateBestCompatibleInQueue(itrQueue, itr->first, itr->second.roles);
713 }
714}
715
716void LFGQueue::UpdateBestCompatibleInQueue(LfgQueueDataContainer::iterator itrQueue, std::string const& key, LfgRolesMap const& roles)
717{
718 LfgQueueData& queueData = itrQueue->second;
719
720 uint8 storedSize = queueData.bestCompatible.empty() ? 0 :
721 std::count(queueData.bestCompatible.begin(), queueData.bestCompatible.end(), '|') + 1;
722
723 uint8 size = std::count(key.begin(), key.end(), '|') + 1;
724
725 if (size <= storedSize)
726 return;
727
728 TC_LOG_DEBUG("lfg.queue.compatibles.update", "Changed ({}) to ({}) as best compatible group for {}",
729 queueData.bestCompatible, key, itrQueue->first.ToString());
730
731 queueData.bestCompatible = key;
732 queueData.tanks = LFG_TANKS_NEEDED;
733 queueData.healers = LFG_HEALERS_NEEDED;
734 queueData.dps = LFG_DPS_NEEDED;
735 for (LfgRolesMap::const_iterator it = roles.begin(); it != roles.end(); ++it)
736 {
737 uint8 role = it->second;
738 if (role & PLAYER_ROLE_TANK)
739 --queueData.tanks;
740 else if (role & PLAYER_ROLE_HEALER)
741 --queueData.healers;
742 else
743 --queueData.dps;
744 }
745}
746
747} // namespace lfg
uint8_t uint8
Definition Define.h:135
int32_t int32
Definition Define.h:129
uint32_t uint32
Definition Define.h:133
#define MAX_GROUP_SIZE
Definition Group.h:43
#define sLFGMgr
Definition LFGMgr.h:492
#define TC_LOG_DEBUG(filterType__,...)
Definition Log.h:156
#define TC_LOG_TRACE(filterType__,...)
Definition Log.h:153
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
std::list< ObjectGuid > GuidList
Definition ObjectGuid.h:261
std::set< ObjectGuid > GuidSet
Definition ObjectGuid.h:260
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:42
static ObjectGuid const Empty
Definition ObjectGuid.h:140
bool IsEmpty() const
Definition ObjectGuid.h:172
uint64 GetRawValue() const
Definition ObjectGuid.h:148
std::string ToString() const
bool IsGroup() const
Definition ObjectGuid.h:189
void Clear()
Definition ObjectGuid.h:150
static bool CheckGroupRoles(LfgRolesMap &groles)
Checks if given roles match, modifies given roles map with new roles.
Definition LFGMgr.cpp:864
static void SendLfgQueueStatus(ObjectGuid guid, LfgQueueStatusData const &data)
Sends queue status to player.
Definition LFGMgr.cpp:1986
void AddQueueData(ObjectGuid guid, time_t joinTime, LfgDungeonSet const &dungeons, LfgRolesMap const &rolesMap)
Definition LFGQueue.cpp:192
LfgCompatibility GetCompatibles(std::string const &key)
Definition LFGQueue.cpp:276
LfgQueueDataContainer QueueDataStore
Queued groups.
Definition LFGQueue.h:134
time_t GetJoinTime(ObjectGuid guid) const
Definition LFGQueue.cpp:639
void UpdateQueueTimers(time_t currTime)
Definition LFGQueue.cpp:589
LfgCompatibilityData * GetCompatibilityData(std::string const &key)
Definition LFGQueue.cpp:285
void UpdateBestCompatibleInQueue(LfgQueueDataContainer::iterator itrQueue, std::string const &key, LfgRolesMap const &roles)
Definition LFGQueue.cpp:716
LfgCompatibility FindNewGroups(GuidList &check, GuidList &all)
Definition LFGQueue.cpp:326
void RemoveQueueData(ObjectGuid guid)
Definition LFGQueue.cpp:198
LfgCompatibleContainer CompatibleMapStore
Compatible dungeons.
Definition LFGQueue.h:135
void AddToQueue(ObjectGuid guid, bool reAdd=false)
Definition LFGQueue.cpp:125
LfgWaitTimesContainer waitTimesTankStore
Average wait time to find a group queuing as tank.
Definition LFGQueue.h:138
void UpdateWaitTimeAvg(int32 waitTime, uint32 dungeonId)
Definition LFGQueue.cpp:205
LfgWaitTimesContainer waitTimesAvgStore
Average wait time to find a group queuing as multiple roles.
Definition LFGQueue.h:137
void RemoveFromQueue(ObjectGuid guid)
Definition LFGQueue.cpp:140
GuidList currentQueueStore
Ordered list. Used to find groups.
Definition LFGQueue.h:141
void RemoveFromNewQueue(ObjectGuid guid)
Definition LFGQueue.cpp:172
void FindBestCompatibleInQueue(LfgQueueDataContainer::iterator itrQueue)
Definition LFGQueue.cpp:701
std::string DumpCompatibleInfo(bool full=false) const
Definition LFGQueue.cpp:674
LfgCompatibility CheckCompatibility(GuidList check)
Definition LFGQueue.cpp:364
void SetCompatibles(std::string const &key, LfgCompatibility compatibles)
Definition LFGQueue.cpp:259
void AddToCurrentQueue(ObjectGuid guid)
Definition LFGQueue.cpp:177
void RemoveFromCompatibles(ObjectGuid guid)
Definition LFGQueue.cpp:238
uint8 FindGroups()
Definition LFGQueue.cpp:294
std::string DumpQueueInfo() const
Definition LFGQueue.cpp:648
void RemoveFromCurrentQueue(ObjectGuid guid)
Definition LFGQueue.cpp:187
void AddToNewQueue(ObjectGuid guid)
Definition LFGQueue.cpp:167
void UpdateWaitTimeHealer(int32 waitTime, uint32 dungeonId)
Definition LFGQueue.cpp:219
GuidList newToQueueStore
New groups to add to queue.
Definition LFGQueue.h:142
void SetCompatibilityData(std::string const &key, LfgCompatibilityData const &compatibles)
Definition LFGQueue.cpp:265
LfgWaitTimesContainer waitTimesDpsStore
Average wait time to find a group queuing as dps.
Definition LFGQueue.h:140
void UpdateWaitTimeTank(int32 waitTime, uint32 dungeonId)
Definition LFGQueue.cpp:212
LfgWaitTimesContainer waitTimesHealerStore
Average wait time to find a group queuing as healer.
Definition LFGQueue.h:139
std::string GetDetailedMatchRoles(GuidList const &check) const
Definition LFGQueue.cpp:88
void UpdateWaitTimeDps(int32 waitTime, uint32 dungeonId)
Definition LFGQueue.cpp:226
void AddToFrontCurrentQueue(ObjectGuid guid)
Definition LFGQueue.cpp:182
time_t GetGameTime()
Definition GameTime.cpp:42
auto SelectRandomContainerElement(C const &container) -> typename std::add_const< decltype(*std::begin(container))>::type &
Definition Containers.h:108
Definition LFG.cpp:24
@ LFG_HEALERS_NEEDED
Definition LFG.h:33
@ LFG_TANKS_NEEDED
Definition LFG.h:32
@ LFG_DPS_NEEDED
Definition LFG.h:34
char const * GetCompatibleString(LfgCompatibility compatibles)
Definition LFGQueue.cpp:55
std::map< ObjectGuid, uint8 > LfgRolesMap
Definition LFG.h:105
@ LFG_STATE_DUNGEON
Definition LFG.h:72
@ LFG_TIME_PROPOSAL
Definition LFGMgr.h:50
@ LFG_ANSWER_AGREE
Definition LFG.h:99
LfgCompatibility
Definition LFGQueue.h:27
@ LFG_COMPATIBLES_WITH_LESS_PLAYERS
Definition LFGQueue.h:35
@ LFG_INCOMPATIBLES_HAS_IGNORES
Definition LFGQueue.h:32
@ LFG_INCOMPATIBLES_MULTIPLE_LFG_GROUPS
Definition LFGQueue.h:31
@ LFG_INCOMPATIBLES_NO_DUNGEONS
Definition LFGQueue.h:34
@ LFG_COMPATIBILITY_PENDING
Definition LFGQueue.h:28
@ LFG_COMPATIBLES_MATCH
Definition LFGQueue.h:37
@ LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS
Definition LFGQueue.h:30
@ LFG_INCOMPATIBLES_WRONG_GROUP_SIZE
Definition LFGQueue.h:29
@ LFG_INCOMPATIBLES_NO_ROLES
Definition LFGQueue.h:33
@ LFG_COMPATIBLES_BAD_STATES
Definition LFGQueue.h:36
std::string ConcatenateGuids(GuidList const &check)
Definition LFGQueue.cpp:37
std::string GetRolesString(uint8 roles)
Definition LFG.cpp:41
std::set< uint32 > LfgDungeonSet
Definition LFG.h:102
std::map< ObjectGuid, ObjectGuid > LfgGroupsMap
Definition LFG.h:106
std::string ConcatenateDungeons(LfgDungeonSet const &dungeons)
Definition LFG.cpp:26
@ PLAYER_ROLE_DAMAGE
Definition LFG.h:43
@ PLAYER_ROLE_TANK
Definition LFG.h:41
@ PLAYER_ROLE_NONE
Definition LFG.h:39
@ PLAYER_ROLE_LEADER
Definition LFG.h:40
@ PLAYER_ROLE_HEALER
Definition LFG.h:42
@ LFG_PROPOSAL_INITIATING
Definition LFGMgr.h:79
LfgCompatibility compatibility
Definition LFGQueue.h:47
Stores player data related to proposal to join.
Definition LFGMgr.h:234
ObjectGuid group
Accept status (-1 not answer | 0 Not agree | 1 agree)
Definition LFGMgr.h:238
LfgAnswer accept
Proposed role.
Definition LFGMgr.h:237
Stores group data related to proposal to join.
Definition LFGMgr.h:243
ObjectGuid leader
Proposal group (0 if new)
Definition LFGMgr.h:252
uint32 dungeonId
Proposal Id.
Definition LFGMgr.h:249
GuidList queues
Determines if it's new group or not.
Definition LFGMgr.h:256
LfgProposalPlayerContainer players
Show order in update window.
Definition LFGMgr.h:258
bool isNew
Dungeon Encounters.
Definition LFGMgr.h:255
LfgProposalState state
Dungeon to join.
Definition LFGMgr.h:250
ObjectGuid group
State of the proposal.
Definition LFGMgr.h:251
time_t cancelTime
Leader guid.
Definition LFGMgr.h:253
Stores player or group queue info.
Definition LFGQueue.h:53
LfgRolesMap roles
Selected Player Role/s.
Definition LFGQueue.h:66
time_t joinTime
Player queue join time (to calculate wait times)
Definition LFGQueue.h:61
std::string bestCompatible
Best compatible combination of people queued.
Definition LFGQueue.h:67
uint8 tanks
Tanks needed.
Definition LFGQueue.h:62
LfgDungeonSet dungeons
Selected Player/Group Dungeon/s.
Definition LFGQueue.h:65
uint8 healers
Healers needed.
Definition LFGQueue.h:63
uint8 dps
Dps needed.
Definition LFGQueue.h:64
int32 time
Wait time.
Definition LFGQueue.h:73
uint32 number
Number of people used to get that wait time.
Definition LFGQueue.h:74