Lobby2Server.cpp 21 KB

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