OregonCore  revision 3611e8a-git
Your Favourite TBC server
LFGHandler.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore 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 "WorldSession.h"
19 #include "Log.h"
20 #include "Database/DatabaseEnv.h"
21 #include "Player.h"
22 #include "WorldPacket.h"
23 #include "ObjectMgr.h"
24 #include "World.h"
25 
26 static void AttemptJoin(Player* _player)
27 {
28  // skip not can autojoin cases and player group case
29  if (!_player->m_lookingForGroup.canAutoJoin() || _player->GetGroup())
30  return;
31 
34  for (HashMapHolder<Player>::MapType::const_iterator iter = players.begin(); iter != players.end(); ++iter)
35  {
36  Player* plr = iter->second;
37 
38  // skip enemies and self
39  if (!plr || plr == _player || plr->GetTeam() != _player->GetTeam())
40  continue;
41 
42  //skip players not in world
43  if (!plr->IsInWorld())
44  continue;
45 
46  // skip not auto add, not group leader cases
47  if (!plr->GetSession()->LookingForGroup_auto_add || (plr->GetGroup() && plr->GetGroup()->GetLeaderGUID() != plr->GetGUID()))
48  continue;
49 
50  // skip non auto-join or empty slots, or non compatible slots
52  continue;
53 
54  // attempt create group, or skip
55  if (!plr->GetGroup())
56  {
57  Group* group = new Group;
58  if (!group->Create(plr->GetGUID(), plr->GetName()))
59  {
60  delete group;
61  continue;
62  }
63 
64  sObjectMgr.AddGroup(group);
65  }
66 
67  // stop at success join
68  if (plr->GetGroup()->AddMember(_player->GetGUID(), _player->GetName()))
69  {
70  if (sWorld.getConfig(CONFIG_RESTRICTED_LFG_CHANNEL) && _player->GetSession()->GetSecurity() == SEC_PLAYER)
71  _player->LeaveLFGChannel();
72  break;
73  }
74  // full
75  else
76  {
78  plr->LeaveLFGChannel();
79  }
80  }
81 }
82 
83 static void AttemptAddMore(Player* _player)
84 {
85  // skip not group leader case
86  if (_player->GetGroup() && _player->GetGroup()->GetLeaderGUID() != _player->GetGUID())
87  return;
88 
89  if (!_player->m_lookingForGroup.more.canAutoJoin())
90  return;
91 
94  for (HashMapHolder<Player>::MapType::const_iterator iter = players.begin(); iter != players.end(); ++iter)
95  {
96  Player* plr = iter->second;
97 
98  // skip enemies and self
99  if (!plr || plr == _player || plr->GetTeam() != _player->GetTeam())
100  continue;
101 
102  if (!plr->IsInWorld())
103  continue;
104 
105  // skip not auto join or in group
106  if (!plr->GetSession()->LookingForGroup_auto_join || plr->GetGroup())
107  continue;
108 
110  continue;
111 
112  // attempt create group if need, or stop attempts
113  if (!_player->GetGroup())
114  {
115  Group* group = new Group;
116  if (!group->Create(_player->GetGUID(), _player->GetName()))
117  {
118  delete group;
119  return; // can't create group (??)
120  }
121 
122  sObjectMgr.AddGroup(group);
123  }
124 
125  // stop at join fail (full)
126  if (!_player->GetGroup()->AddMember(plr->GetGUID(), plr->GetName()))
127  {
128  if (sWorld.getConfig(CONFIG_RESTRICTED_LFG_CHANNEL) && _player->GetSession()->GetSecurity() == SEC_PLAYER)
129  _player->LeaveLFGChannel();
130 
131  break;
132  }
133 
134  // joined
136  plr->LeaveLFGChannel();
137 
138  // and group full
139  if (_player->GetGroup()->IsFull())
140  {
141  if (sWorld.getConfig(CONFIG_RESTRICTED_LFG_CHANNEL) && _player->GetSession()->GetSecurity() == SEC_PLAYER)
142  _player->LeaveLFGChannel();
143 
144  break;
145  }
146  }
147 }
148 
150 {
151  sLog.outDebug("CMSG_SET_LFG_AUTO_JOIN");
153 
154  if (!_player) // needed because STATUS_AUTHED
155  return;
156 
157  AttemptJoin(_player);
158 }
159 
161 {
162  sLog.outDebug("CMSG_UNSET_LFG_AUTO_JOIN");
164 }
165 
167 {
168  sLog.outDebug("CMSG_SET_LFM_AUTOADD");
170 
171  if (!_player) // needed because STATUS_AUTHED
172  return;
173 
174  AttemptAddMore(_player);
175 }
176 
178 {
179  sLog.outDebug("CMSG_UNSET_LFM_AUTOADD");
180  LookingForGroup_auto_add = false;
181 }
182 
184 {
185  sLog.outDebug("CMSG_LOOKING_FOR_GROUP_CLEAR");
186 
187  for (int i = 0; i < MAX_LOOKING_FOR_GROUP_SLOT; ++i)
188  _player->m_lookingForGroup.slots[i].Clear();
189 
190  if (sWorld.getConfig(CONFIG_RESTRICTED_LFG_CHANNEL) && _player->GetSession()->GetSecurity() == SEC_PLAYER)
191  _player->LeaveLFGChannel();
192 }
193 
195 {
196  sLog.outDebug("CMSG_SET_LOOKING_FOR_NONE");
197 
198  _player->m_lookingForGroup.more.Clear();
199 }
200 
202 {
203  sLog.outDebug("CMSG_SET_LOOKING_FOR_MORE");
204 
205  uint32 temp, entry, type;
206  recv_data >> temp;
207 
208  entry = (temp & 0xFFFF);
209  type = ((temp >> 24) & 0xFFFF);
210 
211  _player->m_lookingForGroup.more.Set(entry, type);
212  sLog.outDebug("LFM set: temp %u, zone %u, type %u", temp, entry, type);
213 
215  AttemptAddMore(_player);
216 
217  SendLfgResult(type, entry, 1);
218 }
219 
221 {
222  sLog.outDebug("CMSG_SET_COMMENTARY");
223  //recv_data.hexlike();
224 
225  std::string comment;
226  recv_data >> comment;
227  sLog.outDebug("LFG comment %s", comment.c_str());
228 
229  _player->m_lookingForGroup.comment = comment;
230 }
231 
233 {
234  sLog.outDebug("MSG_LOOKING_FOR_GROUP");
235  //recv_data.hexlike();
236  uint32 type, entry, unk;
237 
238  recv_data >> type >> entry >> unk;
239  sLog.outDebug("MSG_LOOKING_FOR_GROUP: type %u, entry %u, unk %u", type, entry, unk);
240 
242  AttemptAddMore(_player);
243 
245  AttemptJoin(_player);
246 
247  SendLfgResult(type, entry, 0);
248 }
249 
250 void WorldSession::SendLfgResult(uint32 type, uint32 entry, uint8 lfg_type)
251 {
252  uint32 number = 0;
253 
254  // start prepare packet;
256  data << uint32(type); // type
257  data << uint32(entry); // entry from LFGDungeons.dbc
258  data << uint32(0); // count, placeholder
259  data << uint32(0); // count again, strange, placeholder
260 
261  //@todo Guard Player map
263  for (HashMapHolder<Player>::MapType::const_iterator iter = players.begin(); iter != players.end(); ++iter)
264  {
265  Player* plr = iter->second;
266 
267  if (!plr || plr->GetTeam() != _player->GetTeam())
268  continue;
269 
270  if (!plr->IsInWorld())
271  continue;
272 
273  if (!plr->m_lookingForGroup.HaveInSlot(entry, type))
274  continue;
275 
276  ++number;
277 
278  data << plr->GetPackGUID(); // packed guid
279  data << plr->getLevel(); // level
280  data << plr->GetZoneId(); // current zone
281  data << lfg_type; // 0x00 - LFG, 0x01 - LFM
282 
283  for (uint8 j = 0; j < MAX_LOOKING_FOR_GROUP_SLOT; ++j)
284  data << uint32(plr->m_lookingForGroup.slots[j].entry | (plr->m_lookingForGroup.slots[j].type << 24));
285  data << plr->m_lookingForGroup.comment;
286 
287  Group* group = plr->GetGroup();
288  if (group)
289  {
290  data << group->GetMembersCount() - 1; // count of group members without group leader
291  for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
292  {
293  Player* member = itr->GetSource();
294  if (member && member->GetGUID() != plr->GetGUID())
295  {
296  data << member->GetPackGUID(); // packed guid
297  data << member->getLevel(); // player level
298  }
299  }
300  }
301  else
302  data << uint32(0x00);
303  }
304 
305  // fill count placeholders
306  data.put<uint32>(4 + 4, number);
307  data.put<uint32>(4 + 4 + 4, number);
308 
309  SendPacket(&data);
310 }
311 
313 {
314  sLog.outDebug("CMSG_SET_LOOKING_FOR_GROUP");
315  //recv_data.hexlike();
316  uint32 slot, temp, entry, type;
317 
318  recv_data >> slot >> temp;
319 
320  entry = (temp & 0xFFFF);
321  type = ((temp >> 24) & 0xFFFF);
322 
323  if (slot >= MAX_LOOKING_FOR_GROUP_SLOT)
324  return;
325 
326  _player->m_lookingForGroup.slots[slot].Set(entry, type);
327  sLog.outDebug("LFG set: looknumber %u, temp %X, type %u, entry %u", slot, temp, type, entry);
328 
330  AttemptJoin(_player);
331 
332  SendLfgResult(type, entry, 0);
333 }
334 
Group * GetGroup()
Definition: Player.h:2589
bool LookingForGroup_auto_add
Definition: WorldSession.h:223
void HandleLfgSetCommentOpcode(WorldPacket &recv_data)
Definition: LFGHandler.cpp:220
void HandleLfgAutoJoinOpcode(WorldPacket &recv_data)
Definition: LFGHandler.cpp:149
HashMapHolder< Player >::MapType & GetPlayers()
bool canAutoJoin() const
Definition: Player.h:312
void Set(uint32 _entry, uint32 _type)
Definition: Player.h:277
uint32 GetZoneId() const
Definition: Object.cpp:1176
#define sLog
Log class singleton.
Definition: Log.h:187
LookingForGroupSlot more
Definition: Player.h:329
UNORDERED_MAP< uint64, T * > MapType
void HandleSetLfgOpcode(WorldPacket &recv_data)
Definition: LFGHandler.cpp:312
#define sObjectMgr
Definition: ObjectMgr.h:1285
void HandleLfmSetNoneOpcode(WorldPacket &recv_data)
Definition: LFGHandler.cpp:194
void SendPacket(WorldPacket const *packet)
bool HaveInSlot(LookingForGroupSlot const &slot) const
Definition: Player.h:300
void LeaveLFGChannel()
Definition: Player.cpp:4724
bool AddMember(const uint64 &guid, const char *name)
Definition: Group.cpp:282
bool IsFull() const
Definition: Group.h:206
void HandleLfgCancelAutoJoinOpcode(WorldPacket &recv_data)
Definition: LFGHandler.cpp:160
ACE_UINT8 uint8
Definition: Define.h:73
const bool & IsInWorld() const
Definition: Object.h:129
std::string comment
Definition: Player.h:330
void HandleLfmAutoAddMembersOpcode(WorldPacket &recv_data)
Definition: LFGHandler.cpp:166
void put(size_t pos, T value)
Definition: ByteBuffer.h:79
LookingForGroup m_lookingForGroup
Definition: Player.h:2498
void HandleLookingForGroup(WorldPacket &recvPacket)
Definition: LFGHandler.cpp:232
PackedGuid const & GetPackGUID() const
Definition: Object.h:172
GroupReference * GetFirstMember()
Definition: Group.h:304
GroupReference * next()
void HandleLfmCancelAutoAddmembersOpcode(WorldPacket &recv_data)
Definition: LFGHandler.cpp:177
void HandleLfmSetOpcode(WorldPacket &recv_data)
Definition: LFGHandler.cpp:201
bool LookingForGroup_auto_join
Definition: WorldSession.h:222
const char * GetName() const
Definition: Object.h:692
bool canAutoJoin() const
Definition: Player.h:286
void HandleLfgClearOpcode(WorldPacket &recv_data)
Definition: LFGHandler.cpp:183
const uint64 & GetLeaderGUID() const
Definition: Group.h:222
bool Create(const uint64 &guid, const char *name)
Definition: Group.cpp:82
void SendLfgResult(uint32 type, uint32 entry, uint8 lfg_type)
Definition: LFGHandler.cpp:250
uint32 GetMembersCount() const
Definition: Group.h:309
uint32 GetTeam() const
Definition: Player.h:2075
WorldSession * GetSession() const
Definition: Player.h:1959
#define sWorld
Definition: World.h:860
void uint32 GetSecurity() const
Definition: WorldSession.h:96
#define MAX_LOOKING_FOR_GROUP_SLOT
Definition: Player.h:295
ACE_UINT32 uint32
Definition: Define.h:71
uint32 getLevel() const
Definition: Unit.h:1029
Definition: Player.h:922
Definition: Group.h:154
LookingForGroupSlot slots[MAX_LOOKING_FOR_GROUP_SLOT]
Definition: Player.h:328
const uint64 & GetGUID() const
Definition: Object.h:156