1 #include "Lobby2Server.h"
2 #include "RakAssert.h"
3 #include "MessageIdentifiers.h"
4
5 //#define __INTEGRATE_LOBBY2_WITH_ROOMS_PLUGIN
6
7 #ifdef __INTEGRATE_LOBBY2_WITH_ROOMS_PLUGIN
8 #include "RoomsPlugin.h"
9 #endif
10
11 using namespace RakNet;
12
UserCompByUsername(const RakString & key,Lobby2Server::User * const & data)13 int Lobby2Server::UserCompByUsername( const RakString &key, Lobby2Server::User * const &data )
14 {
15 if (key < data->userName)
16 return -1;
17 if (key==data->userName)
18 return 0;
19 return 1;
20 }
21
Lobby2Server()22 Lobby2Server::Lobby2Server()
23 {
24 DataStructures::OrderedList<SystemAddress, SystemAddress>::IMPLEMENT_DEFAULT_COMPARISON();
25 DataStructures::OrderedList<RakString, RakString>::IMPLEMENT_DEFAULT_COMPARISON();
26 roomsPlugin=0;
27 roomsPluginAddress=UNASSIGNED_SYSTEM_ADDRESS;
28 }
~Lobby2Server()29 Lobby2Server::~Lobby2Server()
30 {
31 Clear();
32 }
SendMessage(Lobby2Message * msg,const DataStructures::List<SystemAddress> & recipients)33 void Lobby2Server::SendMessage(Lobby2Message *msg, const DataStructures::List<SystemAddress> &recipients)
34 {
35 RakNet::BitStream bs;
36 bs.Write((MessageID)ID_LOBBY2_SEND_MESSAGE);
37 bs.Write((MessageID)msg->GetID());
38 msg->Serialize(true,true,&bs);
39 SendUnifiedToMultiple(&bs,packetPriority, RELIABLE_ORDERED, orderingChannel, recipients);
40 }
Update(void)41 void Lobby2Server::Update(void)
42 {
43 while (threadActionQueue.Size())
44 {
45 threadActionQueueMutex.Lock();
46 if (threadActionQueue.Size())
47 {
48 ThreadAction ta = threadActionQueue.Pop();
49 threadActionQueueMutex.Unlock();
50 if (ta.action==L2MID_Client_Logoff)
51 {
52 OnLogoff(&ta.command, false);
53 }
54 else if (ta.action==L2MID_Client_Login)
55 {
56 OnLogin(&ta.command, false);
57 }
58 else if (ta.action==L2MID_Client_ChangeHandle)
59 {
60 OnChangeHandle(&ta.command, false);
61 }
62 }
63 else
64 {
65 threadActionQueueMutex.Unlock();
66 break;
67 }
68 }
69
70 if (threadPool.HasOutputFast() && threadPool.HasOutput())
71 {
72 Lobby2ServerCommand c = threadPool.GetOutput();
73 c.lobby2Message->ServerPostDBMemoryImpl(this, c.callingUserName);
74 if (c.returnToSender)
75 {
76 RakNet::BitStream bs;
77 bs.Write((MessageID)ID_LOBBY2_SEND_MESSAGE);
78 bs.Write((MessageID)c.lobby2Message->GetID());
79 c.lobby2Message->Serialize(true,true,&bs);
80 // Have the ID to send to, but not the address. The ID came from the thread, such as notifying another user
81 if (c.callerSystemAddresses.Size()==0)
82 {
83 unsigned int i;
84 if (c.callerUserId!=0)
85 {
86 for (i=0; i < users.Size(); i++)
87 {
88 if (users[i]->callerUserId==c.callerUserId)
89 {
90 c.callerSystemAddresses=users[i]->systemAddresses;
91 c.callerGuids=users[i]->guids;
92
93 /*
94 if (c.requiredConnectionAddress!=UNASSIGNED_SYSTEM_ADDRESS)
95 {
96 // This message refers to another user that has to be logged on for it to be sent
97 bool objectExists;
98 unsigned int idx;
99 idx = users.GetIndexFromKey(c.callerSystemAddress,&objectExists);
100 if (objectExists==false)
101 {
102 if (c.deallocMsgWhenDone)
103 RakNet::OP_DELETE(c.lobby2Message, __FILE__, __LINE__);
104 return;
105 }
106 }
107 */
108 break;
109 }
110 }
111 }
112 if (c.callerSystemAddresses.Size()==0 && c.callingUserName.IsEmpty()==false)
113 {
114 for (i=0; i < users.Size(); i++)
115 {
116 if (users[i]->callerUserId==c.callerUserId)
117 {
118 c.callerSystemAddresses=users[i]->systemAddresses;
119 c.callerGuids=users[i]->guids;
120 break;
121 }
122 }
123 }
124 }
125 else
126 {
127 bool objectExists;
128 unsigned int idx;
129 idx = users.GetIndexFromKey(c.callingUserName,&objectExists);
130 if (objectExists &&
131 c.callingUserName.IsEmpty()==false &&
132 users[idx]->userName!=c.callingUserName)
133 {
134 // Different user, same IP address. Abort the send.
135 if (c.deallocMsgWhenDone)
136 RakNet::OP_DELETE(c.lobby2Message, __FILE__, __LINE__);
137 return;
138 }
139 }
140 SendUnifiedToMultiple(&bs,packetPriority, RELIABLE_ORDERED, orderingChannel, c.callerSystemAddresses);
141 }
142 if (c.deallocMsgWhenDone)
143 RakNet::OP_DELETE(c.lobby2Message, __FILE__, __LINE__);
144 }
145 }
OnReceive(Packet * packet)146 PluginReceiveResult Lobby2Server::OnReceive(Packet *packet)
147 {
148 RakAssert(packet);
149
150 switch (packet->data[0])
151 {
152 case ID_LOBBY2_SEND_MESSAGE:
153 OnMessage(packet);
154 return RR_STOP_PROCESSING_AND_DEALLOCATE;
155 }
156
157 return RR_CONTINUE_PROCESSING;
158 }
OnShutdown(void)159 void Lobby2Server::OnShutdown(void)
160 {
161 Clear();
162 }
OnClosedConnection(SystemAddress systemAddress,RakNetGUID rakNetGUID,PI2_LostConnectionReason lostConnectionReason)163 void Lobby2Server::OnClosedConnection(SystemAddress systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
164 {
165 (void)rakNetGUID;
166 (void)lostConnectionReason;
167
168 unsigned int index = GetUserIndexBySystemAddress(systemAddress);
169
170 // If systemAddress is a user, then notify his friends about him logging off
171 if (index!=-1)
172 {
173 bool found=false;
174 User *user = users[index];
175 for (unsigned int i=0; i < user->systemAddresses.Size(); i++)
176 {
177 if (user->systemAddresses[i]==systemAddress)
178 {
179 found=true;
180 user->systemAddresses.RemoveAtIndexFast(i);
181 break;
182 }
183 }
184
185 if (found && user->systemAddresses.Size()==0)
186 {
187 // Log this logoff due to closed connection
188 Lobby2Message *lobby2Message = msgFactory->Alloc(L2MID_Client_Logoff);
189 Lobby2ServerCommand command;
190 command.lobby2Message=lobby2Message;
191 command.deallocMsgWhenDone=true;
192 command.returnToSender=true;
193 command.callerUserId=users[index]->callerUserId;
194 command.server=this;
195 ExecuteCommand(&command);
196
197 RemoveUser(index);
198 }
199 }
200 }
OnMessage(Packet * packet)201 void Lobby2Server::OnMessage(Packet *packet)
202 {
203 RakNet::BitStream bs(packet->data,packet->length,false);
204 bs.IgnoreBytes(1); // ID_LOBBY2_SEND_MESSAGE
205 MessageID msgId;
206 bs.Read(msgId);
207 Lobby2MessageID lobby2MessageID = (Lobby2MessageID) msgId;
208 unsigned int index;
209 Lobby2Message *lobby2Message = msgFactory->Alloc(lobby2MessageID);
210 if (lobby2Message)
211 {
212 lobby2Message->Serialize(false,false,&bs);
213 Lobby2ServerCommand command;
214 command.lobby2Message=lobby2Message;
215 command.deallocMsgWhenDone=true;
216 command.returnToSender=true;
217 index=GetUserIndexBySystemAddress(packet->systemAddress);
218 if (index!=-1)
219 {
220 command.callingUserName=users[index]->userName;
221 command.callerUserId=users[index]->callerUserId;
222 }
223 else
224 {
225 if (lobby2Message->RequiresLogin())
226 {
227 RakNet::BitStream bs;
228 bs.Write((MessageID)ID_LOBBY2_SEND_MESSAGE);
229 bs.Write((MessageID)lobby2Message->GetID());
230 lobby2Message->resultCode=L2RC_NOT_LOGGED_IN;
231 lobby2Message->Serialize(true,true,&bs);
232 SendUnified(&bs,packetPriority, RELIABLE_ORDERED, orderingChannel, packet->systemAddress, false);
233 return;
234 }
235 command.callerUserId=0;
236 }
237 command.callerSystemAddresses.Push(packet->systemAddress,__FILE__,__LINE__);
238 command.callerGuids.Push(packet->guid,__FILE__,__LINE__);
239 command.server=this;
240 ExecuteCommand(&command);
241 }
242 else
243 {
244 RakNet::BitStream out;
245 out.Write((MessageID)ID_LOBBY2_SERVER_ERROR);
246 out.Write((unsigned char) L2SE_UNKNOWN_MESSAGE_ID);
247 out.Write((unsigned int) msgId);
248 SendUnified(&bs,packetPriority, RELIABLE_ORDERED, orderingChannel, packet->systemAddress, false);
249 }
250 }
Clear(void)251 void Lobby2Server::Clear(void)
252 {
253 ClearAdminAddresses();
254 ClearRankingAddresses();
255 ClearUsers();
256 ClearConnections();
257
258 threadPool.StopThreads();
259 RakAssert(threadPool.NumThreadsWorking()==0);
260
261 unsigned i;
262 Lobby2ServerCommand c;
263 for (i=0; i < threadPool.InputSize(); i++)
264 {
265 c = threadPool.GetInputAtIndex(i);
266 if (c.deallocMsgWhenDone && c.lobby2Message)
267 RakNet::OP_DELETE(c.lobby2Message, __FILE__, __LINE__);
268 }
269 threadPool.ClearInput();
270 for (i=0; i < threadPool.OutputSize(); i++)
271 {
272 c = threadPool.GetOutputAtIndex(i);
273 if (c.deallocMsgWhenDone && c.lobby2Message)
274 RakNet::OP_DELETE(c.lobby2Message, __FILE__, __LINE__);
275 }
276 threadPool.ClearOutput();
277
278 threadActionQueueMutex.Lock();
279 threadActionQueue.Clear(__FILE__, __LINE__);
280 threadActionQueueMutex.Unlock();
281 }
AddAdminAddress(SystemAddress addr)282 void Lobby2Server::AddAdminAddress(SystemAddress addr)
283 {
284 adminAddresses.Insert(addr,addr,false, __FILE__, __LINE__ );
285 }
HasAdminAddress(const DataStructures::List<SystemAddress> & addresses)286 bool Lobby2Server::HasAdminAddress(const DataStructures::List<SystemAddress> &addresses)
287 {
288 if (addresses.Size()==0)
289 return true;
290
291 unsigned int j;
292 for (j=0; j < addresses.Size(); j++)
293 {
294 if (adminAddresses.HasData(addresses[j]))
295 return true;
296 }
297 return false;
298 }
RemoveAdminAddress(SystemAddress addr)299 void Lobby2Server::RemoveAdminAddress(SystemAddress addr)
300 {
301 adminAddresses.RemoveIfExists(addr);
302 }
ClearAdminAddresses(void)303 void Lobby2Server::ClearAdminAddresses(void)
304 {
305 adminAddresses.Clear(false, __FILE__, __LINE__);
306 }
AddRankingAddress(SystemAddress addr)307 void Lobby2Server::AddRankingAddress(SystemAddress addr)
308 {
309 rankingAddresses.Insert(addr,addr,false, __FILE__, __LINE__ );
310 }
HasRankingAddress(const DataStructures::List<SystemAddress> & addresses)311 bool Lobby2Server::HasRankingAddress(const DataStructures::List<SystemAddress> &addresses)
312 {
313 if (addresses.Size()==0)
314 return true;
315
316 unsigned int j;
317 for (j=0; j < addresses.Size(); j++)
318 {
319 if (rankingAddresses.HasData(addresses[j]))
320 return true;
321 }
322 return false;
323 }
RemoveRankingAddress(SystemAddress addr)324 void Lobby2Server::RemoveRankingAddress(SystemAddress addr)
325 {
326 rankingAddresses.RemoveIfExists(addr);
327 }
ClearRankingAddresses(void)328 void Lobby2Server::ClearRankingAddresses(void)
329 {
330 rankingAddresses.Clear(false, __FILE__, __LINE__);
331 }
ExecuteCommand(Lobby2ServerCommand * command)332 void Lobby2Server::ExecuteCommand(Lobby2ServerCommand *command)
333 {
334 RakNet::BitStream out;
335 if (command->lobby2Message->PrevalidateInput()==false)
336 {
337 SendMessage(command->lobby2Message, command->callerSystemAddresses);
338 if (command->deallocMsgWhenDone)
339 msgFactory->Dealloc(command->lobby2Message);
340 return;
341 }
342
343 if (command->lobby2Message->RequiresAdmin() && HasAdminAddress(command->callerSystemAddresses)==false)
344 {
345 command->lobby2Message->resultCode=L2RC_REQUIRES_ADMIN;
346 SendMessage(command->lobby2Message, command->callerSystemAddresses);
347 SendUnifiedToMultiple(&out,packetPriority, RELIABLE_ORDERED, orderingChannel, command->callerSystemAddresses);
348 if (command->deallocMsgWhenDone)
349 msgFactory->Dealloc(command->lobby2Message);
350 return;
351 }
352
353 if (command->lobby2Message->RequiresRankingPermission() && HasRankingAddress(command->callerSystemAddresses)==false)
354 {
355 command->lobby2Message->resultCode=L2RC_REQUIRES_ADMIN;
356 SendMessage(command->lobby2Message, command->callerSystemAddresses);
357 SendUnifiedToMultiple(&out,packetPriority, RELIABLE_ORDERED, orderingChannel, command->callerSystemAddresses);
358 if (command->deallocMsgWhenDone)
359 msgFactory->Dealloc(command->lobby2Message);
360 return;
361 }
362
363 if (command->lobby2Message->ServerPreDBMemoryImpl(this, command->callingUserName)==true)
364 {
365 SendMessage(command->lobby2Message, command->callerSystemAddresses);
366 if (command->deallocMsgWhenDone)
367 msgFactory->Dealloc(command->lobby2Message);
368 return;
369 }
370
371 command->server=this;
372 AddInputCommand(*command);
373 }
SetRoomsPlugin(RoomsPlugin * rp)374 void Lobby2Server::SetRoomsPlugin(RoomsPlugin *rp)
375 {
376 roomsPlugin=rp;
377 roomsPluginAddress=UNASSIGNED_SYSTEM_ADDRESS;
378 }
SetRoomsPluginAddress(SystemAddress address)379 void Lobby2Server::SetRoomsPluginAddress(SystemAddress address)
380 {
381 roomsPluginAddress=address;
382 roomsPlugin=0;
383 }
ClearUsers(void)384 void Lobby2Server::ClearUsers(void)
385 {
386 unsigned int i;
387 for (i=0; i < users.Size(); i++)
388 RakNet::OP_DELETE(users[i], __FILE__, __LINE__);
389 users.Clear(false, __FILE__, __LINE__);
390 }
LogoffFromRooms(User * user)391 void Lobby2Server::LogoffFromRooms(User *user)
392 {
393 // Remove from the room too
394 #if defined(__INTEGRATE_LOBBY2_WITH_ROOMS_PLUGIN)
395 // Tell the rooms plugin about the logoff event
396 if (roomsPlugin)
397 {
398 roomsPlugin->LogoffRoomsParticipant(user->userName, UNASSIGNED_SYSTEM_ADDRESS);
399 }
400 else if (roomsPluginAddress!=UNASSIGNED_SYSTEM_ADDRESS)
401 {
402 RakNet::BitStream bs;
403 RoomsPlugin::SerializeLogoff(user->userName,&bs);
404 SendUnified(&bs,packetPriority, RELIABLE_ORDERED, orderingChannel, roomsPluginAddress, false);
405 }
406 #endif
407
408 }
SendRemoteLoginNotification(RakNet::RakString handle,const DataStructures::List<SystemAddress> & recipients)409 void Lobby2Server::SendRemoteLoginNotification(RakNet::RakString handle, const DataStructures::List<SystemAddress>& recipients)
410 {
411 Notification_Client_RemoteLogin notification;
412 notification.handle=handle;
413 notification.resultCode=L2RC_SUCCESS;
414 SendMessage(¬ification, recipients);
415 }
OnLogin(Lobby2ServerCommand * command,bool calledFromThread)416 void Lobby2Server::OnLogin(Lobby2ServerCommand *command, bool calledFromThread)
417 {
418 if (calledFromThread)
419 {
420 ThreadAction ta;
421 ta.action=L2MID_Client_Login;
422 ta.command=*command;
423 threadActionQueueMutex.Lock();
424 threadActionQueue.Push(ta, __FILE__, __LINE__ );
425 threadActionQueueMutex.Unlock();
426 return;
427 }
428
429 bool objectExists;
430 unsigned int insertionIndex = users.GetIndexFromKey(command->callingUserName, &objectExists);
431 if (objectExists)
432 {
433 User * user = users[insertionIndex];
434 if (user->allowMultipleLogins==false)
435 {
436 SendRemoteLoginNotification(user->userName, user->systemAddresses);
437 LogoffFromRooms(user);
438
439 // Already logged in from this system address.
440 // Delete the existing entry, which will be reinserted.
441 RakNet::OP_DELETE(user,__FILE__,__LINE__);
442 users.RemoveAtIndex(insertionIndex);
443 }
444 else
445 {
446 if (user->systemAddresses.GetIndexOf(command->callerSystemAddresses[0])==(unsigned int) -1)
447 {
448 // Just add system address and guid already in use to the list for this user
449 user->systemAddresses.Push(command->callerSystemAddresses[0], __FILE__, __LINE__);
450 user->guids.Push(command->callerGuids[0], __FILE__, __LINE__);
451 }
452 return;
453 }
454 }
455 else
456 {
457 // Different username, from the same IP address or RakNet instance
458 unsigned int idx2 = GetUserIndexByGUID(command->callerGuids[0]);
459 unsigned int idx3 = GetUserIndexBySystemAddress(command->callerSystemAddresses[0]);
460 if (idx2!=(unsigned int) -1)
461 {
462 User * user = users[idx2];
463 if (user->allowMultipleLogins==true)
464 return;
465 SendRemoteLoginNotification(user->userName, user->systemAddresses);
466 LogoffFromRooms(user);
467
468 RakNet::OP_DELETE(user,__FILE__,__LINE__);
469 users.RemoveAtIndex(idx2);
470
471 insertionIndex = users.GetIndexFromKey(command->callingUserName, &objectExists);
472 }
473 else if (idx3!=(unsigned int) -1)
474 {
475 User * user = users[idx3];
476 if (user->allowMultipleLogins==true)
477 return;
478 SendRemoteLoginNotification(user->userName, user->systemAddresses);
479 LogoffFromRooms(user);
480
481 RakNet::OP_DELETE(user,__FILE__,__LINE__);
482 users.RemoveAtIndex(idx3);
483
484 insertionIndex = users.GetIndexFromKey(command->callingUserName, &objectExists);
485 }
486 }
487
488
489 User *user = RakNet::OP_NEW<User>( __FILE__, __LINE__ );
490 user->userName=command->callingUserName;
491 user->systemAddresses=command->callerSystemAddresses;
492 user->guids=command->callerGuids;
493 user->callerUserId=command->callerUserId;
494 user->allowMultipleLogins=((Client_Login*)command->lobby2Message)->allowMultipleLogins;
495 users.InsertAtIndex(user, insertionIndex, __FILE__, __LINE__ );
496
497 #if defined(__INTEGRATE_LOBBY2_WITH_ROOMS_PLUGIN)
498 // Tell the rooms plugin about the login event
499 if (roomsPlugin)
500 {
501 roomsPlugin->LoginRoomsParticipant(user->userName, user->systemAddresses[0], user->guids[0], UNASSIGNED_SYSTEM_ADDRESS);
502 }
503 else if (roomsPluginAddress!=UNASSIGNED_SYSTEM_ADDRESS)
504 {
505 RakNet::BitStream bs;
506 RoomsPlugin::SerializeLogin(user->userName,user->systemAddresses[0], user->guids[0], &bs);
507 SendUnified(&bs,packetPriority, RELIABLE_ORDERED, orderingChannel, roomsPluginAddress, false);
508 }
509 #endif
510 }
OnLogoff(Lobby2ServerCommand * command,bool calledFromThread)511 void Lobby2Server::OnLogoff(Lobby2ServerCommand *command, bool calledFromThread)
512 {
513 if (calledFromThread)
514 {
515 ThreadAction ta;
516 ta.action=L2MID_Client_Logoff;
517 ta.command=*command;
518 threadActionQueueMutex.Lock();
519 threadActionQueue.Push(ta, __FILE__, __LINE__ );
520 threadActionQueueMutex.Unlock();
521 return;
522 }
523 RemoveUser(command->callingUserName);
524 }
OnChangeHandle(Lobby2ServerCommand * command,bool calledFromThread)525 void Lobby2Server::OnChangeHandle(Lobby2ServerCommand *command, bool calledFromThread)
526 {
527 if (calledFromThread)
528 {
529 ThreadAction ta;
530 ta.action=L2MID_Client_ChangeHandle;
531 ta.command=*command;
532 threadActionQueueMutex.Lock();
533 threadActionQueue.Push(ta, __FILE__, __LINE__ );
534 threadActionQueueMutex.Unlock();
535 return;
536 }
537
538 unsigned int i;
539 RakNet::RakString oldHandle;
540 for (i=0; i < users.Size(); i++)
541 {
542 if (users[i]->callerUserId==command->callerUserId)
543 {
544 oldHandle=users[i]->userName;
545 users[i]->userName=command->callingUserName;
546 break;
547 }
548 }
549
550 if (oldHandle.IsEmpty())
551 return;
552
553 #if defined(__INTEGRATE_LOBBY2_WITH_ROOMS_PLUGIN)
554 // Tell the rooms plugin about the handle change
555 if (roomsPlugin)
556 {
557 roomsPlugin->ChangeHandle(oldHandle, command->callingUserName);
558 }
559 else if (roomsPluginAddress!=UNASSIGNED_SYSTEM_ADDRESS)
560 {
561 RakNet::BitStream bs;
562 RoomsPlugin::SerializeChangeHandle(oldHandle,command->callingUserName,&bs);
563 SendUnified(&bs,packetPriority, RELIABLE_ORDERED, orderingChannel, roomsPluginAddress, false);
564 }
565 #endif
566 }
RemoveUser(RakString userName)567 void Lobby2Server::RemoveUser(RakString userName)
568 {
569 bool objectExists;
570 unsigned int index = users.GetIndexFromKey(userName, &objectExists);
571 if (objectExists)
572 RemoveUser(index);
573 }
RemoveUser(unsigned int index)574 void Lobby2Server::RemoveUser(unsigned int index)
575 {
576 User *user = users[index];
577
578 Lobby2ServerCommand command;
579 Notification_Friends_StatusChange *notification = (Notification_Friends_StatusChange *) GetMessageFactory()->Alloc(L2MID_Notification_Friends_StatusChange);
580 notification->otherHandle=user->userName;
581 notification->op=Notification_Friends_StatusChange::FRIEND_LOGGED_OFF;
582 notification->resultCode=L2RC_SUCCESS;
583 command.server=this;
584 command.deallocMsgWhenDone=true;
585 command.lobby2Message=notification;
586 command.callerUserId=user->callerUserId;
587 command.callingUserName=user->userName;
588 ExecuteCommand(&command);
589
590 unsigned i;
591 i=0;
592 threadPool.LockInput();
593 while (i < threadPool.InputSize())
594 {
595 Lobby2ServerCommand command;
596 command = threadPool.GetInputAtIndex(i);
597 if (command.lobby2Message->CancelOnDisconnect()&& command.callerSystemAddresses.Size()>0 && user->systemAddresses.GetIndexOf(command.callerSystemAddresses[0])!=(unsigned int)-1)
598 {
599 if (command.deallocMsgWhenDone)
600 RakNet::OP_DELETE(command.lobby2Message, __FILE__, __LINE__);
601 threadPool.RemoveInputAtIndex(i);
602 }
603 else
604 i++;
605 }
606 threadPool.UnlockInput();
607 LogoffFromRooms(user);
608
609 RakNet::OP_DELETE(user,__FILE__,__LINE__);
610 users.RemoveAtIndex(index);
611
612 }
GetUserIndexBySystemAddress(SystemAddress systemAddress) const613 unsigned int Lobby2Server::GetUserIndexBySystemAddress(SystemAddress systemAddress) const
614 {
615 unsigned int idx1,idx2;
616 for (idx1=0; idx1 < users.Size(); idx1++)
617 {
618 for (idx2=0; idx2 < users[idx1]->systemAddresses.Size(); idx2++)
619 {
620 if (users[idx1]->systemAddresses[idx2]==systemAddress)
621 return idx1;
622 }
623 }
624 return (unsigned int) -1;
625 }
GetUserIndexByGUID(RakNetGUID guid) const626 unsigned int Lobby2Server::GetUserIndexByGUID(RakNetGUID guid) const
627 {
628 unsigned int idx1,idx2;
629 for (idx1=0; idx1 < users.Size(); idx1++)
630 {
631 for (idx2=0; idx2 < users[idx1]->guids.Size(); idx2++)
632 {
633 if (users[idx1]->guids[idx2]==guid)
634 return idx1;
635 }
636 }
637 return (unsigned int) -1;
638 }
GetUserIndexByUsername(RakNet::RakString userName) const639 unsigned int Lobby2Server::GetUserIndexByUsername(RakNet::RakString userName) const
640 {
641 unsigned int idx;
642 bool objectExists;
643 idx = users.GetIndexFromKey(userName,&objectExists);
644 if (objectExists)
645 return idx;
646 return (unsigned int) -1;
647 }
StopThreads(void)648 void Lobby2Server::StopThreads(void)
649 {
650 threadPool.StopThreads();
651 }
SetConfigurationProperties(ConfigurationProperties c)652 void Lobby2Server::SetConfigurationProperties(ConfigurationProperties c)
653 {
654 configurationProperties=c;
655 }
GetConfigurationProperties(void) const656 const Lobby2Server::ConfigurationProperties *Lobby2Server::GetConfigurationProperties(void) const
657 {
658 return &configurationProperties;
659 }
GetUserOnlineStatus(UsernameAndOnlineStatus & userInfo) const660 void Lobby2Server::GetUserOnlineStatus(UsernameAndOnlineStatus &userInfo) const
661 {
662 unsigned int idx = GetUserIndexByUsername(userInfo.handle);
663 if (idx!=-1)
664 {
665 userInfo.isOnline=true;
666 userInfo.presence=users[idx]->presence;
667 }
668 else
669 {
670 userInfo.isOnline=false;
671 userInfo.presence.status=Lobby2Presence::NOT_ONLINE;
672 userInfo.presence.isVisible=false;
673 }
674 }
SetPresence(const RakNet::Lobby2Presence & presence,RakNet::RakString userHandle)675 void Lobby2Server::SetPresence(const RakNet::Lobby2Presence &presence, RakNet::RakString userHandle)
676 {
677 unsigned int index = GetUserIndexByUsername(userHandle);
678
679 if (index!=-1)
680 {
681 User *user = users[index];
682 user->presence=presence;
683
684 // Push notify presence update to friends
685 Lobby2ServerCommand command;
686 Notification_Friends_PresenceUpdate *notification = (Notification_Friends_PresenceUpdate *) GetMessageFactory()->Alloc(L2MID_Notification_Friends_PresenceUpdate);
687 notification->newPresence=presence;
688 notification->otherHandle=user->userName;
689 notification->resultCode=L2RC_SUCCESS;
690 command.server=this;
691 command.deallocMsgWhenDone=true;
692 command.lobby2Message=notification;
693 command.callerUserId=user->callerUserId;
694 command.callingUserName=user->userName;
695 ExecuteCommand(&command);
696 }
697 }
GetPresence(RakNet::Lobby2Presence & presence,RakNet::RakString userHandle)698 void Lobby2Server::GetPresence(RakNet::Lobby2Presence &presence, RakNet::RakString userHandle)
699 {
700 unsigned int userIndex = GetUserIndexByUsername(userHandle);
701 if (userIndex!=-1)
702 {
703 presence=users[userIndex]->presence;
704 }
705 else
706 {
707 presence.status=Lobby2Presence::NOT_ONLINE;
708 }
709 }
SendUnifiedToMultiple(const RakNet::BitStream * bitStream,PacketPriority priority,PacketReliability reliability,char orderingChannel,const DataStructures::List<SystemAddress> systemAddresses)710 void Lobby2Server::SendUnifiedToMultiple( const RakNet::BitStream * bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, const DataStructures::List<SystemAddress> systemAddresses )
711 {
712 for (unsigned int i=0; i < systemAddresses.Size(); i++)
713 SendUnified(bitStream,priority,reliability,orderingChannel,systemAddresses[i],false);
714 }
715