RoomsContainer.cpp 111 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709
  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 "RoomsContainer.h"
  11. #include "ProfanityFilter.h"
  12. #include "RakAssert.h"
  13. #include "GetTime.h"
  14. #include "BitStream.h"
  15. #include "TableSerializer.h"
  16. static const RakNet::TimeMS MINIMUM_QUICK_JOIN_TIMEOUT=5000;
  17. static const RakNet::TimeMS MAXIMUM_QUICK_JOIN_TIMEOUT=60000 * 5;
  18. static const int MAX_CUSTOM_QUERY_FIELDS=50;
  19. static const RakNet::TimeMS PROCESS_QUICK_JOINS_INTERVAL=1000;
  20. #define QUICK_JOIN_ROOM_NAME "Quick Join "
  21. using namespace RakNet;
  22. DataStructures::Table::FilterQuery RoomQuery::fq[32];
  23. DataStructures::Table::Cell RoomQuery::cells[32];
  24. int AllGamesRoomsContainer::RoomsSortByName( Room* const &key, Room* const &data )
  25. {
  26. return strcmp(key->GetStringProperty(DefaultRoomColumns::TC_ROOM_NAME),data->GetStringProperty(DefaultRoomColumns::TC_ROOM_NAME));
  27. }
  28. // ---------------------------- QuickJoinMember ----------------------------
  29. QuickJoinUser::QuickJoinUser()
  30. {
  31. networkedQuickJoinUser.query.queries=0;
  32. totalTimeWaiting=0;
  33. }
  34. QuickJoinUser::~QuickJoinUser()
  35. {
  36. }
  37. int QuickJoinUser::SortByTotalTimeWaiting( QuickJoinUser* const &key, QuickJoinUser* const &data )
  38. {
  39. if (key->totalTimeWaiting > data->totalTimeWaiting)
  40. return -1;
  41. if (key->totalTimeWaiting < data->totalTimeWaiting)
  42. return 1;
  43. if (key->networkedQuickJoinUser.minimumPlayers > data->networkedQuickJoinUser.minimumPlayers)
  44. return -1;
  45. if (key->networkedQuickJoinUser.minimumPlayers < data->networkedQuickJoinUser.minimumPlayers)
  46. return 1;
  47. if (key->networkedQuickJoinUser.timeout < data->networkedQuickJoinUser.timeout)
  48. return -1;
  49. if (key->networkedQuickJoinUser.timeout > data->networkedQuickJoinUser.timeout)
  50. return 1;
  51. if (key < data)
  52. return -1;
  53. return -1;
  54. }
  55. int QuickJoinUser::SortByMinimumSlots( QuickJoinUser* const &key, QuickJoinUser* const &data )
  56. {
  57. if (key->networkedQuickJoinUser.minimumPlayers > data->networkedQuickJoinUser.minimumPlayers)
  58. return -1;
  59. if (key->networkedQuickJoinUser.minimumPlayers < data->networkedQuickJoinUser.minimumPlayers)
  60. return 1;
  61. if (key->totalTimeWaiting > data->totalTimeWaiting)
  62. return -1;
  63. if (key->totalTimeWaiting < data->totalTimeWaiting)
  64. return 1;
  65. if (key->networkedQuickJoinUser.timeout < data->networkedQuickJoinUser.timeout)
  66. return -1;
  67. if (key->networkedQuickJoinUser.timeout > data->networkedQuickJoinUser.timeout)
  68. return 1;
  69. if (key < data)
  70. return -1;
  71. return -1;
  72. }
  73. void NetworkedQuickJoinUser::Serialize(bool writeToBitstream, RakNet::BitStream *bitStream)
  74. {
  75. query.Serialize(writeToBitstream, bitStream);
  76. bitStream->Serialize(writeToBitstream,timeout);
  77. bitStream->Serialize(writeToBitstream,minimumPlayers);
  78. }
  79. // ---------------------------- RoomMember ----------------------------
  80. RoomMember::RoomMember() {isReady=false; newMemberNotificationProcessed=false; joinTime=0; roomMemberMode=RMM_PUBLIC; roomsParticipant=0;}
  81. RoomMember::~RoomMember() {}
  82. // ---------------------------- Slots ----------------------------
  83. Slots::Slots() {publicSlots=reservedSlots=spectatorSlots=0;}
  84. Slots::~Slots() {}
  85. RoomsErrorCode Slots::Validate(void) const
  86. {
  87. if (publicSlots+reservedSlots < 1)
  88. return REC_SLOTS_VALIDATION_NO_PLAYABLE_SLOTS;
  89. if (publicSlots<0)
  90. return REC_SLOTS_VALIDATION_NEGATIVE_PUBLIC_SLOTS;
  91. if (reservedSlots<0)
  92. return REC_SLOTS_VALIDATION_NEGATIVE_RESERVED_SLOTS;
  93. if (spectatorSlots<0)
  94. return REC_SLOTS_VALIDATION_NEGATIVE_SPECTATOR_SLOTS;
  95. return REC_SUCCESS;
  96. }
  97. void Slots::Serialize(bool writeToBitstream, RakNet::BitStream *bitStream)
  98. {
  99. bitStream->Serialize(writeToBitstream,publicSlots);
  100. bitStream->Serialize(writeToBitstream,reservedSlots);
  101. bitStream->Serialize(writeToBitstream,spectatorSlots);
  102. }
  103. // ---------------------------- InvitedUser ----------------------------
  104. void InvitedUser::Serialize(bool writeToBitstream, RakNet::BitStream *bitStream)
  105. {
  106. if (room)
  107. roomId=room->GetID();
  108. bitStream->Serialize(writeToBitstream,roomId);
  109. bitStream->Serialize(writeToBitstream,invitorName);
  110. bitStream->Serialize(writeToBitstream,invitorSystemAddress);
  111. bitStream->Serialize(writeToBitstream,target);
  112. bitStream->Serialize(writeToBitstream,subject);
  113. bitStream->Serialize(writeToBitstream,body);
  114. bitStream->Serialize(writeToBitstream,invitedAsSpectator);
  115. }
  116. // ---------------------------- BannedUser ----------------------------
  117. void BannedUser::Serialize(bool writeToBitstream, RakNet::BitStream *bitStream)
  118. {
  119. bitStream->Serialize(writeToBitstream, target);
  120. bitStream->Serialize(writeToBitstream, reason);
  121. }
  122. // ---------------------------- RoomMemberDescriptor ----------------------------
  123. void RoomMemberDescriptor::FromRoomMember(RoomMember *roomMember)
  124. {
  125. name=roomMember->roomsParticipant->GetName();
  126. roomMemberMode=roomMember->roomMemberMode;
  127. isReady=roomMember->isReady;
  128. systemAddress=roomMember->roomsParticipant->GetSystemAddress();
  129. guid=roomMember->roomsParticipant->GetGUID();
  130. }
  131. void RoomMemberDescriptor::Serialize(bool writeToBitstream, RakNet::BitStream *bitStream)
  132. {
  133. bitStream->Serialize(writeToBitstream, name);
  134. bitStream->Serialize(writeToBitstream, roomMemberMode);
  135. bitStream->Serialize(writeToBitstream, isReady);
  136. bitStream->Serialize(writeToBitstream, systemAddress);
  137. bitStream->Serialize(writeToBitstream, guid);
  138. }
  139. // ---------------------------- RemoveUserResult ----------------------------
  140. RemoveUserResult::RemoveUserResult()
  141. {
  142. removedFromQuickJoin=false;
  143. removedFromRoom=false;
  144. room=0;
  145. gotNewModerator=false;
  146. roomDestroyed=false;
  147. }
  148. RemoveUserResult::~RemoveUserResult()
  149. {
  150. }
  151. void RemoveUserResult::Serialize(bool writeToBitstream, RakNet::BitStream *bitStream)
  152. {
  153. bitStream->Serialize(writeToBitstream,removedFromQuickJoin);
  154. bitStream->Serialize(writeToBitstream,removedFromRoom);
  155. if (room)
  156. roomId=room->GetID();
  157. bitStream->Serialize(writeToBitstream,roomId);
  158. bitStream->Serialize(writeToBitstream,removedUserName);
  159. bitStream->Serialize(writeToBitstream,removedUserAddress);
  160. bitStream->Serialize(writeToBitstream,gotNewModerator);
  161. bitStream->Serialize(writeToBitstream,roomDestroyed);
  162. unsigned int clearedInvitationsSize=clearedInvitations.Size();
  163. bitStream->Serialize(writeToBitstream,clearedInvitationsSize);
  164. if (writeToBitstream==false)
  165. {
  166. clearedInvitations.Clear(false, _FILE_AND_LINE_);
  167. InvitedUser invitedUser;
  168. for (unsigned i=0; i < clearedInvitationsSize; i++)
  169. {
  170. invitedUser.Serialize(writeToBitstream, bitStream);
  171. clearedInvitations.Insert(invitedUser, _FILE_AND_LINE_ );
  172. }
  173. }
  174. }
  175. // ---------------------------- JoinedRoomResult ----------------------------
  176. void JoinedRoomResult::Serialize(bool writeToBitstream, RakNet::BitStream *bitStream)
  177. {
  178. if (acceptedInvitor)
  179. {
  180. acceptedInvitorName=acceptedInvitor->GetName();
  181. acceptedInvitorAddress=acceptedInvitor->GetSystemAddress();
  182. }
  183. if (joiningMember)
  184. {
  185. joiningMemberName=joiningMember->GetName();
  186. joiningMemberAddress=joiningMember->GetSystemAddress();
  187. joiningMemberGuid=joiningMember->GetGUID();
  188. }
  189. bitStream->Serialize(writeToBitstream, acceptedInvitorName);
  190. bitStream->Serialize(writeToBitstream, joiningMemberName);
  191. bitStream->Serialize(writeToBitstream, acceptedInvitorAddress);
  192. bitStream->Serialize(writeToBitstream, joiningMemberAddress);
  193. bitStream->Serialize(writeToBitstream, joiningMemberGuid);
  194. roomDescriptor.FromRoom(roomOutput, agrc);
  195. roomDescriptor.Serialize(writeToBitstream, bitStream);
  196. }
  197. // ---------------------------- RoomDescriptor ----------------------------
  198. void RoomDescriptor::FromRoom(Room *room, AllGamesRoomsContainer *agrc)
  199. {
  200. if (room==0)
  201. return;
  202. Clear();
  203. roomLockState=room->roomLockState;
  204. lobbyRoomId=room->lobbyRoomId;
  205. autoLockReadyStatus=room->autoLockReadyStatus;
  206. hiddenFromSearches=room->hiddenFromSearches;
  207. inviteToRoomPermission=room->inviteToRoomPermission;
  208. inviteToSpectatorSlotPermission=room->inviteToSpectatorSlotPermission;
  209. RoomMemberDescriptor rmd;
  210. unsigned int i;
  211. for (i=0; i < room->roomMemberList.Size(); i++)
  212. {
  213. rmd.FromRoomMember(room->roomMemberList[i]);
  214. roomMemberList.Insert(rmd, _FILE_AND_LINE_ );
  215. }
  216. for (i=0; i < room->banList.Size(); i++)
  217. {
  218. banList.Insert(room->banList[i], _FILE_AND_LINE_ );
  219. }
  220. RakAssert(agrc);
  221. if (agrc)
  222. {
  223. Room *r;
  224. agrc->GetRoomProperties(room->GetID(), &r, &roomProperties);
  225. }
  226. }
  227. void RoomDescriptor::Serialize(bool writeToBitstream, RakNet::BitStream *bitStream)
  228. {
  229. bitStream->Serialize(writeToBitstream, roomLockState);
  230. bitStream->Serialize(writeToBitstream, lobbyRoomId);
  231. bitStream->Serialize(writeToBitstream, autoLockReadyStatus);
  232. bitStream->Serialize(writeToBitstream, hiddenFromSearches);
  233. bitStream->Serialize(writeToBitstream, inviteToRoomPermission);
  234. bitStream->Serialize(writeToBitstream, inviteToSpectatorSlotPermission);
  235. unsigned int i;
  236. unsigned int roomMemberListSize, banListSize;
  237. roomMemberListSize=roomMemberList.Size();
  238. bitStream->Serialize(writeToBitstream, roomMemberListSize);
  239. for (i=0; i < roomMemberListSize; i++)
  240. {
  241. RoomMemberDescriptor rmd;
  242. if (writeToBitstream==false)
  243. {
  244. rmd.Serialize(writeToBitstream, bitStream);
  245. roomMemberList.Insert(rmd, _FILE_AND_LINE_ );
  246. }
  247. else
  248. roomMemberList[i].Serialize(writeToBitstream, bitStream);
  249. }
  250. banListSize=banList.Size();
  251. bitStream->Serialize(writeToBitstream, banListSize);
  252. for (i=0; i < banListSize; i++)
  253. {
  254. BannedUser bu;
  255. if (writeToBitstream==false)
  256. bu.Serialize(writeToBitstream, bitStream);
  257. else
  258. banList[i].Serialize(writeToBitstream, bitStream);
  259. }
  260. if (writeToBitstream)
  261. TableSerializer::SerializeTable(&roomProperties, bitStream);
  262. else
  263. TableSerializer::DeserializeTable(bitStream, &roomProperties);
  264. }
  265. // ---------------------------- RoomQuery ----------------------------
  266. RoomsErrorCode RoomQuery::Validate(void)
  267. {
  268. if (numQueries > DefaultRoomColumns::TC_TABLE_COLUMNS_COUNT+MAX_CUSTOM_QUERY_FIELDS)
  269. return REC_ROOM_QUERY_TOO_MANY_QUERIES;
  270. if (numQueries>0 && queries==0)
  271. return REC_ROOM_QUERY_INVALID_QUERIES_POINTER;
  272. return REC_SUCCESS;
  273. }
  274. void RoomQuery::Serialize(bool writeToBitstream, RakNet::BitStream *bitStream)
  275. {
  276. bool hasQuery = numQueries!=0;
  277. bitStream->Serialize(writeToBitstream,hasQuery);
  278. if (hasQuery)
  279. {
  280. bitStream->Serialize(writeToBitstream,numQueries);
  281. unsigned int i;
  282. for (i=0; i < numQueries; i++)
  283. {
  284. if (writeToBitstream)
  285. TableSerializer::SerializeFilterQuery(bitStream, &queries[i]);
  286. else
  287. TableSerializer::DeserializeFilterQuery(bitStream, &queries[i]);
  288. }
  289. }
  290. }
  291. // ---------------------------- RoomCreationParameters ----------------------------
  292. void NetworkedRoomCreationParameters::Serialize(bool writeToBitstream, RakNet::BitStream *bitStream)
  293. {
  294. slots.Serialize(writeToBitstream, bitStream);
  295. bitStream->Serialize(writeToBitstream,hiddenFromSearches);
  296. bitStream->Serialize(writeToBitstream,destroyOnModeratorLeave);
  297. bitStream->Serialize(writeToBitstream,autoLockReadyStatus);
  298. bitStream->Serialize(writeToBitstream,inviteToRoomPermission);
  299. bitStream->Serialize(writeToBitstream,inviteToSpectatorSlotPermission);
  300. bitStream->Serialize(writeToBitstream,clearInvitesOnNewModerator);
  301. bitStream->Serialize(writeToBitstream,roomName);
  302. }
  303. const char *NetworkedRoomCreationParameters::SendInvitePermissionToEnum(SendInvitePermission e)
  304. {
  305. switch (e)
  306. {
  307. case INVITE_MODE_ANYONE_CAN_INVITE:
  308. return "INVITE_MODE_ANYONE_CAN_INVITE";
  309. case INVITE_MODE_MODERATOR_CAN_INVITE:
  310. return "INVITE_MODE_MODERATOR_CAN_INVITE";
  311. case INVITE_MODE_PUBLIC_SLOTS_CAN_INVITE:
  312. return "INVITE_MODE_PUBLIC_SLOTS_CAN_INVITE";
  313. case INVITE_MODE_RESERVED_SLOTS_CAN_INVITE:
  314. return "INVITE_MODE_RESERVED_SLOTS_CAN_INVITE";
  315. case INVITE_MODE_SPECTATOR_SLOTS_CAN_INVITE:
  316. return "INVITE_MODE_SPECTATOR_SLOTS_CAN_INVITE";
  317. case INVITE_MODE_MODERATOR_OR_PUBLIC_SLOTS_CAN_INVITE:
  318. return "INVITE_MODE_MODERATOR_OR_PUBLIC_SLOTS_CAN_INVITE";
  319. case INVITE_MODE_MODERATOR_OR_PUBLIC_OR_RESERVED_SLOTS_CAN_INVITE:
  320. return "INVITE_MODE_MODERATOR_OR_PUBLIC_OR_RESERVED_SLOTS_CAN_INVITE";
  321. }
  322. return "Error in NetworkedRoomCreationParameters::SendInvitePermissionToEnum";
  323. }
  324. RoomCreationParameters::RoomCreationParameters()
  325. {
  326. networkedRoomCreationParameters.hiddenFromSearches=false;
  327. networkedRoomCreationParameters.destroyOnModeratorLeave=false;
  328. firstUser=0;
  329. createdRoom=false;
  330. roomOutput=0;
  331. networkedRoomCreationParameters.inviteToRoomPermission=NetworkedRoomCreationParameters::INVITE_MODE_ANYONE_CAN_INVITE;
  332. networkedRoomCreationParameters.inviteToSpectatorSlotPermission=NetworkedRoomCreationParameters::INVITE_MODE_ANYONE_CAN_INVITE;
  333. networkedRoomCreationParameters.clearInvitesOnNewModerator=false;
  334. }
  335. RoomCreationParameters::~RoomCreationParameters()
  336. {
  337. }
  338. RoomsErrorCode RoomCreationParameters::Validate(const DataStructures::List<RakNet::RakString> &otherRoomNames,
  339. ProfanityFilter *profanityFilter) const
  340. {
  341. static size_t QUICK_JOIN_ROOM_NAME_LENGTH = strlen(QUICK_JOIN_ROOM_NAME);
  342. if (networkedRoomCreationParameters.roomName.IsEmpty())
  343. return REC_ROOM_CREATION_PARAMETERS_EMPTY_ROOM_NAME;
  344. if (profanityFilter && profanityFilter->HasProfanity(networkedRoomCreationParameters.roomName.C_String()))
  345. return REC_ROOM_CREATION_PARAMETERS_ROOM_NAME_HAS_PROFANITY;
  346. if (otherRoomNames.GetIndexOf(networkedRoomCreationParameters.roomName)!=(unsigned)-1)
  347. return REC_ROOM_CREATION_PARAMETERS_ROOM_NAME_IN_USE;
  348. if (networkedRoomCreationParameters.slots.publicSlots+networkedRoomCreationParameters.slots.reservedSlots<1)
  349. return REC_ROOM_CREATION_PARAMETERS_NO_PLAYABLE_SLOTS;
  350. if (networkedRoomCreationParameters.roomName.SubStr(0,(unsigned int) QUICK_JOIN_ROOM_NAME_LENGTH)==QUICK_JOIN_ROOM_NAME)
  351. return REC_ROOM_CREATION_PARAMETERS_RESERVED_QUICK_JOIN_ROOM_NAME;
  352. return REC_SUCCESS;
  353. }
  354. // ---------------------------- RoomQuery ----------------------------
  355. RoomQuery::RoomQuery() {queries=0; numQueries=0; queriesAllocated=false; SetQueriesToStatic();}
  356. RoomQuery::~RoomQuery() {}
  357. void RoomQuery::AddQuery_NUMERIC(const char *columnName, double numericValue, DataStructures::Table::FilterQueryType op)
  358. {
  359. SetupNextQuery(columnName,op);
  360. cells[numQueries].Set(numericValue);
  361. numQueries++;
  362. }
  363. void RoomQuery::AddQuery_STRING(const char *columnName, const char *charValue, DataStructures::Table::FilterQueryType op)
  364. {
  365. if (charValue==0 || charValue[0]==0)
  366. return;
  367. SetupNextQuery(columnName,op);
  368. cells[numQueries].Set(charValue);
  369. numQueries++;
  370. }
  371. void RoomQuery::AddQuery_BINARY(const char *columnName, const char *input, int inputLength, DataStructures::Table::FilterQueryType op)
  372. {
  373. if (input==0 || input[0]==0 || inputLength==0)
  374. return;
  375. SetupNextQuery(columnName,op);
  376. cells[numQueries].Set(input, inputLength);
  377. numQueries++;
  378. }
  379. void RoomQuery::AddQuery_POINTER(const char *columnName, void *ptr, DataStructures::Table::FilterQueryType op)
  380. {
  381. SetupNextQuery(columnName,op);
  382. cells[numQueries].SetPtr(ptr);
  383. numQueries++;
  384. }
  385. void RoomQuery::SetupNextQuery(const char *columnName,DataStructures::Table::FilterQueryType op)
  386. {
  387. queries=(DataStructures::Table::FilterQuery *)fq;
  388. fq[numQueries].cellValue=&cells[numQueries];
  389. strcpy(fq[numQueries].columnName, columnName);
  390. fq[numQueries].operation=op;
  391. }
  392. void RoomQuery::SetQueriesToStatic(void)
  393. {
  394. queries = (DataStructures::Table::FilterQuery *)fq;
  395. for (int i=0; i < 32; i++)
  396. {
  397. fq[i].cellValue=&cells[i];
  398. }
  399. }
  400. // ---------------------------- AllGamesRoomsContainer ----------------------------
  401. AllGamesRoomsContainer::AllGamesRoomsContainer()
  402. {
  403. DataStructures::Map<GameIdentifier, PerGameRoomsContainer*>::IMPLEMENT_DEFAULT_COMPARISON();
  404. nextRoomId=0;
  405. }
  406. AllGamesRoomsContainer::~AllGamesRoomsContainer()
  407. {
  408. }
  409. RoomsErrorCode AllGamesRoomsContainer::CreateRoom(RoomCreationParameters *roomCreationParameters,
  410. ProfanityFilter *profanityFilter)
  411. {
  412. if (roomCreationParameters->firstUser->GetRoom())
  413. return REC_CREATE_ROOM_CURRENTLY_IN_A_ROOM;
  414. else if (roomCreationParameters->firstUser->GetInQuickJoin())
  415. return REC_CREATE_ROOM_CURRENTLY_IN_QUICK_JOIN;
  416. if (perGamesRoomsContainers.Has(roomCreationParameters->gameIdentifier)==false)
  417. return REC_CREATE_ROOM_UNKNOWN_TITLE;
  418. PerGameRoomsContainer *perGameRoomsContainer = perGamesRoomsContainers.Get(roomCreationParameters->gameIdentifier);
  419. RoomsErrorCode roomsErrorCode = perGameRoomsContainer->CreateRoom(roomCreationParameters,profanityFilter,++nextRoomId, true);
  420. if (roomsErrorCode!=REC_SUCCESS)
  421. nextRoomId--;
  422. return roomsErrorCode;
  423. }
  424. RoomsErrorCode AllGamesRoomsContainer::EnterRoom(RoomCreationParameters *roomCreationParameters,
  425. RoomMemberMode roomMemberMode,
  426. ProfanityFilter *profanityFilter,
  427. RoomQuery *query,
  428. JoinedRoomResult *joinRoomResult)
  429. {
  430. roomCreationParameters->roomOutput=0;
  431. joinRoomResult->roomOutput=0;
  432. joinRoomResult->agrc=this;
  433. if (roomCreationParameters->firstUser->GetRoom())
  434. return REC_ENTER_ROOM_CURRENTLY_IN_A_ROOM;
  435. else if (roomCreationParameters->firstUser->GetInQuickJoin())
  436. return REC_ENTER_ROOM_CURRENTLY_IN_QUICK_JOIN;
  437. roomCreationParameters->createdRoom=false;
  438. if (perGamesRoomsContainers.Has(roomCreationParameters->gameIdentifier)==false)
  439. return REC_ENTER_ROOM_UNKNOWN_TITLE;
  440. PerGameRoomsContainer *perGameRoomsContainer = perGamesRoomsContainers.Get(roomCreationParameters->gameIdentifier);
  441. RoomsErrorCode roomsErrorCode = perGameRoomsContainer->JoinByFilter(roomMemberMode, roomCreationParameters->firstUser, (RakNet::RoomID) -1, query, joinRoomResult);
  442. // Redundant, rooms plugin does this anyway
  443. // if (roomsErrorCode==REC_SUCCESS)
  444. // joinRoomResult->roomDescriptor.FromRoom(joinRoomResult->roomOutput, this);
  445. if (roomsErrorCode != REC_JOIN_BY_FILTER_NO_ROOMS || roomsErrorCode==REC_SUCCESS)
  446. return roomsErrorCode;
  447. roomsErrorCode = perGameRoomsContainer->CreateRoom(roomCreationParameters,profanityFilter,++nextRoomId, true);
  448. if (roomsErrorCode!=REC_SUCCESS)
  449. {
  450. nextRoomId--;
  451. }
  452. else
  453. {
  454. roomCreationParameters->createdRoom=true;
  455. }
  456. return roomsErrorCode;
  457. }
  458. RoomsErrorCode AllGamesRoomsContainer::JoinByFilter(GameIdentifier gameIdentifier, RoomMemberMode roomMemberMode, RoomsParticipant* roomsParticipant, RoomID lastRoomJoined, RoomQuery *query, JoinedRoomResult *joinRoomResult)
  459. {
  460. (void) lastRoomJoined;
  461. if (roomsParticipant->GetRoom())
  462. return REC_JOIN_BY_FILTER_CURRENTLY_IN_A_ROOM;
  463. else if (roomsParticipant->GetInQuickJoin())
  464. return REC_JOIN_BY_FILTER_CURRENTLY_IN_QUICK_JOIN;
  465. if (perGamesRoomsContainers.Has(gameIdentifier)==false)
  466. {
  467. joinRoomResult->roomOutput=0;
  468. return REC_JOIN_BY_FILTER_UNKNOWN_TITLE;
  469. }
  470. PerGameRoomsContainer *perGameRoomsContainer = perGamesRoomsContainers.Get(gameIdentifier);
  471. joinRoomResult->agrc=this;
  472. RoomsErrorCode rec = perGameRoomsContainer->JoinByFilter(roomMemberMode, roomsParticipant, (RakNet::RoomID) -1, query, joinRoomResult);
  473. joinRoomResult->roomDescriptor.FromRoom(joinRoomResult->roomOutput, this);
  474. return rec;
  475. }
  476. RoomsErrorCode AllGamesRoomsContainer::LeaveRoom(RoomsParticipant* roomsParticipant, RemoveUserResult *removeUserResult)
  477. {
  478. if (roomsParticipant->GetRoom()==false)
  479. return REC_LEAVE_ROOM_NOT_IN_ROOM;
  480. else if (roomsParticipant->GetInQuickJoin())
  481. return REC_LEAVE_ROOM_CURRENTLY_IN_QUICK_JOIN;
  482. RoomsErrorCode roomsErrorCode = roomsParticipant->GetRoom()->RemoveUser(roomsParticipant, removeUserResult);
  483. return roomsErrorCode;
  484. }
  485. RoomsErrorCode AllGamesRoomsContainer::AddUserToQuickJoin(GameIdentifier gameIdentifier, QuickJoinUser *quickJoinMember)
  486. {
  487. if (quickJoinMember->roomsParticipant->GetRoom())
  488. return REC_ADD_TO_QUICK_JOIN_CURRENTLY_IN_A_ROOM;
  489. else if (quickJoinMember->roomsParticipant->GetInQuickJoin())
  490. return REC_ADD_TO_QUICK_JOIN_ALREADY_THERE;
  491. if (perGamesRoomsContainers.Has(gameIdentifier)==false)
  492. return REC_ADD_TO_QUICK_JOIN_UNKNOWN_TITLE;
  493. if (quickJoinMember->networkedQuickJoinUser.timeout < MINIMUM_QUICK_JOIN_TIMEOUT)
  494. return REC_ADD_TO_QUICK_JOIN_INVALID_TIMEOUT_TOO_LOW;
  495. if (quickJoinMember->networkedQuickJoinUser.timeout > MAXIMUM_QUICK_JOIN_TIMEOUT)
  496. return REC_ADD_TO_QUICK_JOIN_INVALID_TIMEOUT_TOO_HIGH;
  497. if (quickJoinMember->networkedQuickJoinUser.minimumPlayers<2)
  498. return REC_ADD_TO_QUICK_JOIN_MINIMUM_SLOTS_TOO_LOW;
  499. if (quickJoinMember->networkedQuickJoinUser.minimumPlayers>5000) // Pretty arbitrary, but who would have this many members in a room?
  500. return REC_ADD_TO_QUICK_JOIN_MINIMUM_SLOTS_TOO_HIGH;
  501. return perGamesRoomsContainers.Get(gameIdentifier)->AddUserToQuickJoin(quickJoinMember);
  502. }
  503. RoomsErrorCode AllGamesRoomsContainer::RemoveUserFromQuickJoin(RoomsParticipant* roomsParticipant, QuickJoinUser **qju)
  504. {
  505. RoomsErrorCode roomsErrorCode;
  506. unsigned int i;
  507. for (i=0; i < perGamesRoomsContainers.Size(); i++)
  508. {
  509. roomsErrorCode = perGamesRoomsContainers[i]->RemoveUserFromQuickJoin(roomsParticipant, qju);
  510. if (roomsErrorCode!=REC_REMOVE_FROM_QUICK_JOIN_NOT_THERE)
  511. return roomsErrorCode;
  512. }
  513. return REC_REMOVE_FROM_QUICK_JOIN_NOT_THERE;
  514. }
  515. bool AllGamesRoomsContainer::IsInQuickJoin(RoomsParticipant* roomsParticipant)
  516. {
  517. unsigned int i;
  518. for (i=0; i < perGamesRoomsContainers.Size(); i++)
  519. if (perGamesRoomsContainers[i]->IsInQuickJoin(roomsParticipant))
  520. return true;
  521. return false;
  522. }
  523. RoomsErrorCode AllGamesRoomsContainer::SearchByFilter( GameIdentifier gameIdentifier, RoomsParticipant* roomsParticipant, RoomQuery *roomQuery, DataStructures::OrderedList<Room*, Room*, RoomsSortByName> &roomsOutput, bool onlyJoinable )
  524. {
  525. roomsOutput.Clear(false, _FILE_AND_LINE_);
  526. if (perGamesRoomsContainers.Has(gameIdentifier)==false)
  527. return REC_SEARCH_BY_FILTER_UNKNOWN_TITLE;
  528. PerGameRoomsContainer *perGameRoomsContainer = perGamesRoomsContainers.Get(gameIdentifier);
  529. return perGameRoomsContainer->SearchByFilter(roomsParticipant, roomQuery, roomsOutput, onlyJoinable);
  530. }
  531. void AllGamesRoomsContainer::DestroyRoomIfDead(Room *room)
  532. {
  533. if (room==0 || room->IsRoomDead()==false)
  534. return;
  535. unsigned int i;
  536. for (i=0; i < perGamesRoomsContainers.Size(); i++)
  537. {
  538. if (perGamesRoomsContainers[i]->DestroyRoomIfDead(room))
  539. break;
  540. }
  541. }
  542. void AllGamesRoomsContainer::ChangeHandle(RakNet::RakString oldHandle, RakNet::RakString newHandle)
  543. {
  544. unsigned int i;
  545. for (i=0; i < perGamesRoomsContainers.Size(); i++)
  546. perGamesRoomsContainers[i]->ChangeHandle(oldHandle, newHandle);
  547. }
  548. unsigned int AllGamesRoomsContainer::GetPropertyIndex(RoomID lobbyRoomId, const char *propertyName) const
  549. {
  550. unsigned int i;
  551. Room *room;
  552. for (i=0; i < perGamesRoomsContainers.Size(); i++)
  553. {
  554. room = perGamesRoomsContainers[i]->GetRoomByLobbyRoomID(lobbyRoomId);
  555. if (room)
  556. return perGamesRoomsContainers[i]->roomsTable.ColumnIndex(propertyName);
  557. }
  558. return (unsigned int) -1;
  559. }
  560. RoomsErrorCode AllGamesRoomsContainer::GetInvitesToParticipant(RoomsParticipant* roomsParticipant, DataStructures::List<InvitedUser*> &invites)
  561. {
  562. unsigned int i;
  563. invites.Clear(true, _FILE_AND_LINE_ );
  564. for (i=0; i < perGamesRoomsContainers.Size(); i++)
  565. perGamesRoomsContainers[i]->GetInvitesToParticipant(roomsParticipant, invites);
  566. return REC_SUCCESS;
  567. }
  568. // userLocation is optional, but will speed up the function if it's pre-known
  569. RoomsErrorCode AllGamesRoomsContainer::RemoveUser(RoomsParticipant* roomsParticipant, RemoveUserResult *removeUserResult)
  570. {
  571. if (RemoveUserFromQuickJoin(roomsParticipant, &removeUserResult->qju)!=REC_SUCCESS)
  572. {
  573. removeUserResult->qju=0;
  574. removeUserResult->removedFromQuickJoin=false;
  575. if (roomsParticipant->GetRoom()==0)
  576. return REC_REMOVE_USER_NOT_IN_ROOM;
  577. RoomsErrorCode roomsErrorCode = roomsParticipant->GetRoom()->RemoveUser(roomsParticipant, removeUserResult);
  578. // if (removeUserResult->roomDestroyed)
  579. // roomsParticipant->GetPerGameRoomsContainer()->roomsTable.RemoveRow(roomsParticipant->GetRoom()->GetID());
  580. return roomsErrorCode;
  581. }
  582. removeUserResult->removedFromQuickJoin=true;
  583. return REC_SUCCESS;
  584. }
  585. RoomsErrorCode AllGamesRoomsContainer::SendInvite(RoomsParticipant* roomsParticipant, RoomsParticipant* inviteeId, bool inviteToSpectatorSlot, RakNet::RakString subject, RakNet::RakString body)
  586. {
  587. if (roomsParticipant->GetRoom()==0)
  588. return REC_SEND_INVITE_UNKNOWN_ROOM_ID;
  589. return roomsParticipant->GetRoom()->SendInvite(roomsParticipant, inviteeId, inviteToSpectatorSlot, subject, body);
  590. }
  591. RoomsErrorCode AllGamesRoomsContainer::AcceptInvite(RoomID roomId, Room **room, RoomsParticipant* roomsParticipant, RakNet::RakString inviteSender)
  592. {
  593. *room = GetRoomByLobbyRoomID(roomId);
  594. if (*room==0)
  595. return REC_ACCEPT_INVITE_UNKNOWN_ROOM_ID;
  596. if (roomsParticipant->GetRoom())
  597. return REC_ACCEPT_INVITE_CURRENTLY_IN_A_ROOM;
  598. if (roomsParticipant->GetInQuickJoin())
  599. return REC_ACCEPT_INVITE_CURRENTLY_IN_QUICK_JOIN;
  600. return (*room)->AcceptInvite(roomsParticipant, inviteSender);
  601. }
  602. RoomsErrorCode AllGamesRoomsContainer::StartSpectating(RoomsParticipant* roomsParticipant)
  603. {
  604. if (roomsParticipant->GetRoom()==0)
  605. return REC_START_SPECTATING_UNKNOWN_ROOM_ID;
  606. return roomsParticipant->GetRoom()->StartSpectating(roomsParticipant);
  607. }
  608. RoomsErrorCode AllGamesRoomsContainer::StopSpectating(RoomsParticipant* roomsParticipant)
  609. {
  610. if (roomsParticipant->GetRoom()==0)
  611. return REC_STOP_SPECTATING_UNKNOWN_ROOM_ID;
  612. return roomsParticipant->GetRoom()->StopSpectating(roomsParticipant);
  613. }
  614. RoomsErrorCode AllGamesRoomsContainer::GrantModerator(RoomsParticipant* roomsParticipant, RoomsParticipant *newModerator, DataStructures::List<InvitedUser> &clearedInvites)
  615. {
  616. if (roomsParticipant->GetRoom()==0)
  617. return REC_GRANT_MODERATOR_UNKNOWN_ROOM_ID;
  618. return roomsParticipant->GetRoom()->GrantModerator(roomsParticipant, newModerator, clearedInvites);
  619. }
  620. RoomsErrorCode AllGamesRoomsContainer::ChangeSlotCounts(RoomsParticipant* roomsParticipant, Slots slots)
  621. {
  622. if (roomsParticipant->GetRoom()==0)
  623. return REC_CHANGE_SLOT_COUNTS_UNKNOWN_ROOM_ID;
  624. return roomsParticipant->GetRoom()->ChangeSlotCounts(roomsParticipant, slots);
  625. }
  626. RoomsErrorCode AllGamesRoomsContainer::SetCustomRoomProperties(RoomsParticipant* roomsParticipant, DataStructures::Table *table)
  627. {
  628. if (roomsParticipant->GetRoom()==0)
  629. return REC_SET_CUSTOM_ROOM_PROPERTIES_UNKNOWN_ROOM_ID;
  630. RoomsErrorCode roomsErrorCode = roomsParticipant->GetRoom()->SetCustomRoomProperties(roomsParticipant, table);
  631. if (roomsErrorCode!=REC_SUCCESS)
  632. return roomsErrorCode;
  633. unsigned int perGamesRoomContainersIndex;
  634. for (perGamesRoomContainersIndex=0; perGamesRoomContainersIndex < perGamesRoomsContainers.Size(); perGamesRoomContainersIndex++)
  635. {
  636. if (perGamesRoomsContainers[perGamesRoomContainersIndex]->GetRoomByLobbyRoomID(roomsParticipant->GetRoom()->GetID()))
  637. break;
  638. }
  639. RakAssert(perGamesRoomContainersIndex != perGamesRoomsContainers.Size());
  640. PerGameRoomsContainer *perGameRoomsContainer = perGamesRoomsContainers[perGamesRoomContainersIndex];
  641. unsigned int newTableIndex, oldTableIndex;
  642. DataStructures::Table *oldTable = &perGameRoomsContainer->roomsTable;
  643. DataStructures::Table::Row *row;
  644. for (newTableIndex=0; newTableIndex < table->GetColumnCount(); newTableIndex++)
  645. {
  646. oldTableIndex = oldTable->ColumnIndex(table->ColumnName(newTableIndex));
  647. if (oldTableIndex==(unsigned int) -1)
  648. {
  649. if (oldTable->GetColumnCount() < (unsigned int) MAX_CUSTOM_QUERY_FIELDS)
  650. {
  651. oldTable->AddColumn(table->ColumnName(newTableIndex), table->GetColumnType(newTableIndex));
  652. }
  653. else
  654. continue;
  655. }
  656. oldTableIndex=oldTable->ColumnIndex(table->ColumnName(newTableIndex));
  657. row = roomsParticipant->GetRoom()->tableRow;
  658. *(row->cells[oldTableIndex])=*(table->GetRowByIndex(0,0)->cells[newTableIndex]);
  659. }
  660. return REC_SUCCESS;
  661. }
  662. void AllGamesRoomsContainer::GetRoomProperties(RoomID roomId, Room **room, DataStructures::Table *table)
  663. {
  664. table->Clear();
  665. unsigned int perGamesRoomContainersIndex;
  666. for (perGamesRoomContainersIndex=0; perGamesRoomContainersIndex < perGamesRoomsContainers.Size(); perGamesRoomContainersIndex++)
  667. {
  668. *room=perGamesRoomsContainers[perGamesRoomContainersIndex]->GetRoomByLobbyRoomID(roomId);
  669. if (*room)
  670. break;
  671. }
  672. RakAssert(perGamesRoomContainersIndex != perGamesRoomsContainers.Size());
  673. PerGameRoomsContainer *perGameRoomsContainer = perGamesRoomsContainers[perGamesRoomContainersIndex];
  674. DataStructures::Table *oldTable = &perGameRoomsContainer->roomsTable;
  675. unsigned int i;
  676. for (i=0; i < oldTable->GetColumnCount(); i++)
  677. table->AddColumn(oldTable->ColumnName(i), oldTable->GetColumnType(i));
  678. table->AddRow(roomId, oldTable->GetRowByID(roomId)->cells, true);
  679. }
  680. RoomsErrorCode AllGamesRoomsContainer::ChangeRoomName(RoomsParticipant* roomsParticipant, RakNet::RakString newRoomName, ProfanityFilter *profanityFilter)
  681. {
  682. if (roomsParticipant->GetRoom()==0)
  683. return REC_CHANGE_ROOM_NAME_UNKNOWN_ROOM_ID;
  684. unsigned int i;
  685. DataStructures::List<RakNet::RakString> roomNames;
  686. for (i=0; i < perGamesRoomsContainers.Size(); i++)
  687. {
  688. perGamesRoomsContainers[i]->GetRoomNames(roomNames);
  689. if (roomNames.GetIndexOf(newRoomName)!=(unsigned int) -1)
  690. return REC_CHANGE_ROOM_NAME_NAME_ALREADY_IN_USE;
  691. }
  692. return roomsParticipant->GetRoom()->ChangeRoomName(roomsParticipant, newRoomName, profanityFilter);
  693. }
  694. RoomsErrorCode AllGamesRoomsContainer::SetHiddenFromSearches(RoomsParticipant* roomsParticipant, bool _hiddenFromSearches)
  695. {
  696. if (roomsParticipant->GetRoom()==0)
  697. return REC_SET_HIDDEN_FROM_SEARCHES_UNKNOWN_ROOM_ID;
  698. return roomsParticipant->GetRoom()->SetHiddenFromSearches(roomsParticipant, _hiddenFromSearches);
  699. }
  700. RoomsErrorCode AllGamesRoomsContainer::SetDestroyOnModeratorLeave(RoomsParticipant* roomsParticipant, bool destroyOnModeratorLeave)
  701. {
  702. if (roomsParticipant->GetRoom()==0)
  703. return REC_SET_DESTROY_ON_MODERATOR_LEAVE_UNKNOWN_ROOM_ID;
  704. return roomsParticipant->GetRoom()->SetDestroyOnModeratorLeave(roomsParticipant, destroyOnModeratorLeave);
  705. }
  706. RoomsErrorCode AllGamesRoomsContainer::SetReadyStatus(RoomsParticipant* roomsParticipant, bool isReady)
  707. {
  708. if (roomsParticipant->GetRoom()==0)
  709. return REC_SET_READY_STATUS_UNKNOWN_ROOM_ID;
  710. return roomsParticipant->GetRoom()->SetReadyStatus(roomsParticipant, isReady);
  711. }
  712. RoomsErrorCode AllGamesRoomsContainer::GetReadyStatus( RoomID roomId, Room **room, DataStructures::List<RoomsParticipant*> &readyUsers, DataStructures::List<RoomsParticipant*> &unreadyUsers)
  713. {
  714. *room = GetRoomByLobbyRoomID(roomId);
  715. if (room==0)
  716. return REC_GET_READY_STATUS_UNKNOWN_ROOM_ID;
  717. return (*room)->GetReadyStatus(readyUsers, unreadyUsers);
  718. }
  719. RoomsErrorCode AllGamesRoomsContainer::SetRoomLockState(RoomsParticipant* roomsParticipant, RoomLockState _roomLockState)
  720. {
  721. if (roomsParticipant->GetRoom()==0)
  722. return REC_SET_ROOM_LOCK_STATE_UNKNOWN_ROOM_ID;
  723. return roomsParticipant->GetRoom()->SetRoomLockState(roomsParticipant, _roomLockState);
  724. }
  725. RoomsErrorCode AllGamesRoomsContainer::GetRoomLockState(RoomID roomId, Room **room, RoomLockState *roomLockState)
  726. {
  727. *room = GetRoomByLobbyRoomID(roomId);
  728. if (*room==0)
  729. return REC_GET_ROOM_LOCK_STATE_UNKNOWN_ROOM_ID;
  730. return (*room)->GetRoomLockState( roomLockState);
  731. }
  732. RoomsErrorCode AllGamesRoomsContainer::AreAllMembersReady(RoomID roomId, Room **room, bool *allReady)
  733. {
  734. *room = GetRoomByLobbyRoomID(roomId);
  735. if (*room==0)
  736. return REC_ARE_ALL_MEMBERS_READY_UNKNOWN_ROOM_ID;
  737. return (RoomsErrorCode) (*room)->AreAllMembersReady((unsigned int) -1, allReady);
  738. }
  739. RoomsErrorCode AllGamesRoomsContainer::KickMember(RoomsParticipant* roomsParticipant, RoomsParticipant *kickedParticipant, RakNet::RakString reason)
  740. {
  741. if (roomsParticipant->GetRoom()==0)
  742. return REC_KICK_MEMBER_UNKNOWN_ROOM_ID;
  743. return roomsParticipant->GetRoom()->KickMember(roomsParticipant, kickedParticipant, reason);
  744. }
  745. RoomsErrorCode AllGamesRoomsContainer::UnbanMember(RoomsParticipant* roomsParticipant, RakNet::RakString name)
  746. {
  747. if (roomsParticipant->GetRoom()==0)
  748. return REC_UNBAN_MEMBER_UNKNOWN_ROOM_ID;
  749. return roomsParticipant->GetRoom()->UnbanMember(roomsParticipant, name);
  750. }
  751. RoomsErrorCode AllGamesRoomsContainer::GetBanReason( RoomID lobbyRoomId, Room **room, RakNet::RakString name, RakNet::RakString *reason)
  752. {
  753. *room = GetRoomByLobbyRoomID(lobbyRoomId);
  754. if (*room==0)
  755. return REC_GET_BAN_REASON_UNKNOWN_ROOM_ID;
  756. return (*room)->GetBanReason(name, reason);
  757. }
  758. /*
  759. RoomsErrorCode AllGamesRoomsContainer::GetKickReason(RoomsParticipant* roomsParticipant, RakNet::RakString *kickReason)
  760. {
  761. *room = GetRoomByLobbyRoomID(lobbyRoomId);
  762. if (*room==0)
  763. return REC_GET_KICK_REASON_UNKNOWN_ROOM_ID;
  764. return roomsParticipant->GetRoom()->GetKickReason(roomsParticipant, kickReason);
  765. }
  766. */
  767. Room * AllGamesRoomsContainer::GetRoomByLobbyRoomID(RoomID lobbyRoomID)
  768. {
  769. unsigned int i;
  770. Room *room;
  771. for (i=0; i < perGamesRoomsContainers.Size(); i++)
  772. {
  773. room = perGamesRoomsContainers[i]->GetRoomByLobbyRoomID(lobbyRoomID);
  774. if (room)
  775. return room;
  776. }
  777. return 0;
  778. }
  779. Room * AllGamesRoomsContainer::GetRoomByName(RakNet::RakString roomName)
  780. {
  781. unsigned int i;
  782. Room *room;
  783. for (i=0; i < perGamesRoomsContainers.Size(); i++)
  784. {
  785. room = perGamesRoomsContainers[i]->GetRoomByName(roomName);
  786. if (room)
  787. return room;
  788. }
  789. return 0;
  790. }
  791. RoomsErrorCode AllGamesRoomsContainer::ProcessQuickJoins(
  792. DataStructures::List<QuickJoinUser*> &timeoutExpired,
  793. DataStructures::List<JoinedRoomResult> &joinedRoomMembers,
  794. DataStructures::List<QuickJoinUser*> &dereferencedPointers,
  795. RakNet::TimeMS elapsedTime)
  796. {
  797. unsigned int numRoomsCreated;
  798. unsigned int i;
  799. dereferencedPointers.Clear(false, _FILE_AND_LINE_);
  800. joinedRoomMembers.Clear(false, _FILE_AND_LINE_);
  801. for (i=0; i < perGamesRoomsContainers.Size(); i++)
  802. {
  803. numRoomsCreated=perGamesRoomsContainers[i]->ProcessQuickJoins(timeoutExpired, joinedRoomMembers, dereferencedPointers, elapsedTime, nextRoomId);
  804. nextRoomId += numRoomsCreated;
  805. }
  806. unsigned int j;
  807. for (j=0; j < joinedRoomMembers.Size(); j++)
  808. joinedRoomMembers[j].agrc=this;
  809. return REC_SUCCESS;
  810. }
  811. RoomsErrorCode AllGamesRoomsContainer::AddTitle(GameIdentifier gameIdentifier)
  812. {
  813. if (perGamesRoomsContainers.Has(gameIdentifier)==true)
  814. return REC_ADD_TITLE_ALREADY_IN_USE;
  815. perGamesRoomsContainers.SetNew(gameIdentifier, new PerGameRoomsContainer);
  816. return REC_SUCCESS;
  817. }
  818. // ---------------------------- PerGameRoomsContainer ----------------------------
  819. PerGameRoomsContainer::PerGameRoomsContainer()
  820. {
  821. DefaultRoomColumns::AddDefaultColumnsToTable(&roomsTable);
  822. nextQuickJoinProcess.SetPeriod(PROCESS_QUICK_JOINS_INTERVAL);
  823. }
  824. PerGameRoomsContainer::~PerGameRoomsContainer()
  825. {
  826. }
  827. RoomsErrorCode PerGameRoomsContainer::CreateRoom(RoomCreationParameters *roomCreationParameters,
  828. ProfanityFilter *profanityFilter,
  829. RoomID lobbyRoomId,
  830. bool validate)
  831. {
  832. if (validate)
  833. {
  834. DataStructures::List<RakNet::RakString> otherRoomNames;
  835. GetRoomNames(otherRoomNames);
  836. RoomsErrorCode roomsErrorCode = roomCreationParameters->Validate(otherRoomNames, profanityFilter);
  837. if (roomsErrorCode!=REC_SUCCESS)
  838. return roomsErrorCode;
  839. roomCreationParameters->createdRoom=true;
  840. }
  841. DataStructures::List<DataStructures::Table::Cell> initialCellValues;
  842. DataStructures::Table::Row *row = roomsTable.AddRow(lobbyRoomId,initialCellValues);
  843. roomCreationParameters->roomOutput = new Room(lobbyRoomId, roomCreationParameters, row, roomCreationParameters->firstUser);
  844. roomCreationParameters->firstUser->SetPerGameRoomsContainer(this);
  845. RakAssert(roomCreationParameters->firstUser->GetRoom()==roomCreationParameters->roomOutput);
  846. return REC_SUCCESS;
  847. }
  848. RoomsErrorCode PerGameRoomsContainer::JoinByFilter(RoomMemberMode roomMemberMode, RoomsParticipant* roomsParticipant, RoomID lastRoomJoined, RoomQuery *query, JoinedRoomResult *joinRoomResult)
  849. {
  850. joinRoomResult->roomOutput=0;
  851. if (roomMemberMode==RMM_MODERATOR)
  852. return REC_JOIN_BY_FILTER_CANNOT_JOIN_AS_MODERATOR;
  853. RoomsErrorCode roomsErrorCode;
  854. if (query!=0)
  855. {
  856. roomsErrorCode = query->Validate();
  857. if (roomsErrorCode!=REC_SUCCESS)
  858. return roomsErrorCode;
  859. }
  860. DataStructures::OrderedList<Room*, Room*, PerGameRoomsContainer::RoomsSortByTimeThenTotalSlots> roomsOutput;
  861. RoomPrioritySort( roomsParticipant, query, roomsOutput );
  862. if (roomsOutput.Size()==0)
  863. return REC_JOIN_BY_FILTER_NO_ROOMS;
  864. if (roomsOutput[0]->GetID()==lastRoomJoined && roomsOutput.Size()>1)
  865. joinRoomResult->roomOutput = roomsOutput[1];
  866. else
  867. joinRoomResult->roomOutput = roomsOutput[0];
  868. roomsParticipant->SetPerGameRoomsContainer(this);
  869. return (joinRoomResult->roomOutput)->JoinByFilter(roomsParticipant, roomMemberMode, joinRoomResult);
  870. }
  871. RoomsErrorCode PerGameRoomsContainer::AddUserToQuickJoin(QuickJoinUser *quickJoinMember)
  872. {
  873. if (GetQuickJoinIndex(quickJoinMember->roomsParticipant)!=(unsigned int) -1)
  874. return REC_ADD_TO_QUICK_JOIN_ALREADY_THERE;
  875. quickJoinMember->roomsParticipant->SetPerGameRoomsContainer(this);
  876. quickJoinMember->roomsParticipant->SetInQuickJoin(true);
  877. quickJoinList.Insert(quickJoinMember, _FILE_AND_LINE_ );
  878. return REC_SUCCESS;
  879. }
  880. RoomsErrorCode PerGameRoomsContainer::RemoveUserFromQuickJoin(RoomsParticipant* roomsParticipant, QuickJoinUser **qju)
  881. {
  882. unsigned int quickJoinIndex = GetQuickJoinIndex(roomsParticipant);
  883. *qju=0;
  884. if (quickJoinIndex==(unsigned int) -1)
  885. return REC_REMOVE_FROM_QUICK_JOIN_NOT_THERE;
  886. quickJoinList[quickJoinIndex]->roomsParticipant->SetInQuickJoin(false);
  887. *qju=quickJoinList[quickJoinIndex];
  888. quickJoinList.RemoveAtIndex(quickJoinIndex);
  889. roomsParticipant->SetPerGameRoomsContainer(0);
  890. return REC_SUCCESS;
  891. }
  892. bool PerGameRoomsContainer::IsInQuickJoin(RoomsParticipant* roomsParticipant)
  893. {
  894. return roomsParticipant->GetInQuickJoin()!=0;
  895. }
  896. int PerGameRoomsContainer::RoomsSortByTimeThenTotalSlots( Room* const &key, Room* const &data )
  897. {
  898. double keyCreationTime = key->GetNumericProperty(DefaultRoomColumns::TC_CREATION_TIME);
  899. double dataCreationTime = data->GetNumericProperty(DefaultRoomColumns::TC_CREATION_TIME);
  900. int diff = (int) abs(keyCreationTime-dataCreationTime);
  901. if (diff < 30 * 1000)
  902. {
  903. double keyTotalSlots = key->GetNumericProperty(DefaultRoomColumns::TC_USED_PUBLIC_PLUS_RESERVED_SLOTS);
  904. double dataTotalSlots = data->GetNumericProperty(DefaultRoomColumns::TC_USED_PUBLIC_PLUS_RESERVED_SLOTS);
  905. if (keyTotalSlots > dataTotalSlots)
  906. return -1;
  907. if (keyTotalSlots < dataTotalSlots)
  908. return 1;
  909. if (key < data)
  910. return -1;
  911. return 1;
  912. }
  913. if (keyCreationTime < dataCreationTime)
  914. return -1;
  915. if (keyCreationTime > dataCreationTime)
  916. return 1;
  917. return strcmp(key->GetStringProperty(DefaultRoomColumns::TC_ROOM_NAME),data->GetStringProperty(DefaultRoomColumns::TC_ROOM_NAME));
  918. }
  919. unsigned PerGameRoomsContainer::ProcessQuickJoins( DataStructures::List<QuickJoinUser*> &timeoutExpired,
  920. DataStructures::List<JoinedRoomResult> &joinedRoomMembers,
  921. DataStructures::List<QuickJoinUser*> &dereferencedPointers,
  922. RakNet::TimeMS elapsedTime,
  923. RoomID startingRoomId)
  924. {
  925. unsigned roomIndex, quickJoinIndex;
  926. for (quickJoinIndex=0; quickJoinIndex < quickJoinList.Size(); quickJoinIndex++)
  927. quickJoinList[quickJoinIndex]->totalTimeWaiting+=elapsedTime;
  928. // This is slow, so don't do it very often
  929. if (nextQuickJoinProcess.UpdateInterval(elapsedTime)==false)
  930. return 0;
  931. unsigned numRoomsCreated=0;
  932. RoomsErrorCode roomsErrorCode;
  933. Room *room;
  934. double totalRoomSlots, remainingRoomSlots;
  935. DataStructures::OrderedList<Room*, Room*, RoomsSortByTimeThenTotalSlots> potentialRooms;
  936. DataStructures::OrderedList<QuickJoinUser *, QuickJoinUser *, QuickJoinUser::SortByTotalTimeWaiting> quickJoinMemberTimeSort;
  937. DataStructures::List<Room*> allRooms;
  938. GetAllRooms(allRooms);
  939. while (1)
  940. {
  941. // 1. Clear all quickJoinWorkingList from all rooms
  942. for (roomIndex=0; roomIndex < allRooms.Size(); roomIndex++)
  943. allRooms[roomIndex]->quickJoinWorkingList.Clear(true, _FILE_AND_LINE_ );
  944. // 2. Use RoomPrioritySort to get all rooms they can potentially join
  945. // 3. For each of these rooms, record that this member can potentially join by storing a copy of the pointer into quickJoinWorkingList, if minimumPlayers => total room slots
  946. for (quickJoinIndex=0; quickJoinIndex < quickJoinList.Size(); quickJoinIndex++)
  947. {
  948. RoomPrioritySort( quickJoinList[quickJoinIndex]->roomsParticipant, &quickJoinList[quickJoinIndex]->networkedQuickJoinUser.query, potentialRooms );
  949. for (roomIndex=0; roomIndex < potentialRooms.Size(); roomIndex++)
  950. {
  951. totalRoomSlots = potentialRooms[roomIndex]->GetNumericProperty(DefaultRoomColumns::TC_TOTAL_PUBLIC_PLUS_RESERVED_SLOTS);
  952. if (totalRoomSlots >= quickJoinList[quickJoinIndex]->networkedQuickJoinUser.minimumPlayers-1 &&
  953. potentialRooms[roomIndex]->ParticipantCanJoinRoom(quickJoinList[quickJoinIndex]->roomsParticipant, false, true)==PCJRR_SUCCESS )
  954. potentialRooms[roomIndex]->quickJoinWorkingList.Insert( quickJoinList[quickJoinIndex], _FILE_AND_LINE_ );
  955. }
  956. }
  957. // For all rooms:
  958. // 4. For each room where there are enough potential quick join members to fill the room, join all those members at once. Remove these members from the quick join list. Go to 1.
  959. for (roomIndex=0; roomIndex < allRooms.Size(); roomIndex++)
  960. {
  961. room = allRooms[roomIndex];
  962. remainingRoomSlots = room->GetNumericProperty(DefaultRoomColumns::TC_REMAINING_PUBLIC_PLUS_RESERVED_SLOTS);
  963. if (remainingRoomSlots>0 && room->quickJoinWorkingList.Size() >= (unsigned int) remainingRoomSlots)
  964. {
  965. quickJoinMemberTimeSort.Clear(false, _FILE_AND_LINE_ );
  966. // Sort those waiting in quick join from longest waiting to least waiting. Those longest waiting are processed first
  967. for (quickJoinIndex=0; quickJoinIndex < (int) room->quickJoinWorkingList.Size(); quickJoinIndex++)
  968. quickJoinMemberTimeSort.Insert( room->quickJoinWorkingList[quickJoinIndex], room->quickJoinWorkingList[quickJoinIndex], true, _FILE_AND_LINE_ );
  969. for (quickJoinIndex=0; quickJoinIndex < (unsigned) remainingRoomSlots; quickJoinIndex++)
  970. {
  971. JoinedRoomResult jrr;
  972. jrr.roomOutput=room;
  973. roomsErrorCode=room->JoinByQuickJoin(quickJoinMemberTimeSort[quickJoinIndex]->roomsParticipant, RMM_ANY_PLAYABLE, &jrr);
  974. RakAssert(roomsErrorCode==REC_SUCCESS);
  975. dereferencedPointers.Insert(quickJoinMemberTimeSort[quickJoinIndex], _FILE_AND_LINE_ );
  976. joinedRoomMembers.Insert(jrr, _FILE_AND_LINE_ );
  977. QuickJoinUser *qju;
  978. roomsErrorCode=RemoveUserFromQuickJoin(quickJoinMemberTimeSort[quickJoinIndex]->roomsParticipant, &qju);
  979. RakAssert(roomsErrorCode==REC_SUCCESS);
  980. }
  981. continue;
  982. }
  983. }
  984. break;
  985. }
  986. DataStructures::OrderedList<QuickJoinUser *, QuickJoinUser *, QuickJoinUser::SortByMinimumSlots> quickJoinMemberSlotSort;
  987. // 5. Sort quick join members by minimumPlayers, excluding members where minimumPlayers > total number of quick join members
  988. for (quickJoinIndex=0; quickJoinIndex < quickJoinList.Size(); quickJoinIndex++)
  989. {
  990. if (quickJoinList[quickJoinIndex]->networkedQuickJoinUser.minimumPlayers <= (int) quickJoinList.Size())
  991. quickJoinMemberSlotSort.Insert(quickJoinList[quickJoinIndex],quickJoinList[quickJoinIndex],true, _FILE_AND_LINE_ );
  992. }
  993. DataStructures::Table potentialNewRoom;
  994. unsigned queryIndex, quickJoinIndex2;
  995. DataStructures::Table resultTable;
  996. QuickJoinUser *quickJoinMember;
  997. RoomCreationParameters roomCreationParameters;
  998. DataStructures::List<QuickJoinUser*> potentialNewRoommates;
  999. // 6. If the current member created a roomOutput, find out how many subsequent members would join based on the custom filter
  1000. quickJoinIndex=0;
  1001. while (quickJoinIndex < quickJoinList.Size())
  1002. {
  1003. quickJoinMember = quickJoinList[quickJoinIndex];
  1004. potentialNewRoom.Clear();
  1005. DefaultRoomColumns::AddDefaultColumnsToTable(&potentialNewRoom);
  1006. DataStructures::Table::Row *row = potentialNewRoom.AddRow(0);
  1007. roomCreationParameters.networkedRoomCreationParameters.slots.publicSlots=quickJoinMember->networkedQuickJoinUser.minimumPlayers-1;
  1008. Room::UpdateRowSlots( row, &roomCreationParameters.networkedRoomCreationParameters.slots, &roomCreationParameters.networkedRoomCreationParameters.slots);
  1009. for (queryIndex=0; queryIndex < quickJoinMember->networkedQuickJoinUser.query.numQueries; queryIndex++)
  1010. {
  1011. // For all filters that are equal and custom, create a table with rows with these values
  1012. if ( ( quickJoinMember->networkedQuickJoinUser.query.queries[queryIndex].operation==DataStructures::Table::QF_EQUAL ) &&
  1013. DefaultRoomColumns::HasColumnName(quickJoinMember->networkedQuickJoinUser.query.queries[queryIndex].columnName)==false &&
  1014. potentialNewRoom.ColumnIndex(quickJoinMember->networkedQuickJoinUser.query.queries[queryIndex].columnName)==-1 &&
  1015. quickJoinMember->networkedQuickJoinUser.query.queries[queryIndex].cellValue->isEmpty==false
  1016. )
  1017. {
  1018. potentialNewRoom.AddColumn(quickJoinMember->networkedQuickJoinUser.query.queries[queryIndex].columnName, quickJoinMember->networkedQuickJoinUser.query.queries[queryIndex].cellValue->EstimateColumnType());
  1019. *(row->cells[potentialNewRoom.GetColumnCount()-1]) = *(quickJoinMember->networkedQuickJoinUser.query.queries[queryIndex].cellValue);
  1020. }
  1021. }
  1022. potentialNewRoommates.Clear(true, _FILE_AND_LINE_ );
  1023. for (quickJoinIndex2=quickJoinIndex+1; quickJoinIndex2 < quickJoinList.Size(); quickJoinIndex2++)
  1024. {
  1025. resultTable.Clear();
  1026. unsigned columnIndices[1];
  1027. columnIndices[0]=DefaultRoomColumns::TC_LOBBY_ROOM_PTR;
  1028. JoinedRoomResult joinedRoomResult;
  1029. DataStructures::Table::FilterQuery subQueries[MAX_CUSTOM_QUERY_FIELDS];
  1030. unsigned int subQueryCount;
  1031. unsigned int subQueryIndex;
  1032. for (subQueryIndex=0, subQueryCount=0; subQueryIndex < quickJoinList[quickJoinIndex2]->networkedQuickJoinUser.query.numQueries; subQueryIndex++)
  1033. {
  1034. if (potentialNewRoom.ColumnIndex(quickJoinList[quickJoinIndex2]->networkedQuickJoinUser.query.queries[subQueryIndex].columnName)!=-1)
  1035. {
  1036. subQueries[subQueryCount++]=quickJoinList[quickJoinIndex2]->networkedQuickJoinUser.query.queries[subQueryIndex];
  1037. }
  1038. }
  1039. potentialNewRoom.QueryTable(columnIndices,1,subQueries,subQueryCount,0,0,&resultTable);
  1040. if (resultTable.GetRowCount()>0)
  1041. {
  1042. potentialNewRoommates.Insert(quickJoinList[quickJoinIndex2], _FILE_AND_LINE_ );
  1043. if (potentialNewRoommates.Size()>=(unsigned int) quickJoinMember->networkedQuickJoinUser.minimumPlayers-1)
  1044. {
  1045. // 7. If this satisfies minimumPlayers, have that user create a roomOutput and those subsequent members join.
  1046. roomCreationParameters.networkedRoomCreationParameters.hiddenFromSearches=false;
  1047. roomCreationParameters.networkedRoomCreationParameters.destroyOnModeratorLeave=false;
  1048. roomCreationParameters.networkedRoomCreationParameters.roomName.Set(QUICK_JOIN_ROOM_NAME "%i", startingRoomId+numRoomsCreated);
  1049. roomCreationParameters.firstUser=quickJoinMember->roomsParticipant;
  1050. roomsErrorCode = CreateRoom(&roomCreationParameters, 0,startingRoomId+numRoomsCreated, false);
  1051. joinedRoomResult.roomOutput=roomCreationParameters.roomOutput;
  1052. numRoomsCreated++;
  1053. RakAssert(roomsErrorCode==REC_SUCCESS);
  1054. QuickJoinUser *qju;
  1055. for (quickJoinIndex2=0; quickJoinIndex2 < potentialNewRoommates.Size(); quickJoinIndex2++)
  1056. {
  1057. roomsErrorCode = roomCreationParameters.roomOutput->JoinByQuickJoin(potentialNewRoommates[quickJoinIndex2]->roomsParticipant, RMM_PUBLIC, &joinedRoomResult);
  1058. RakAssert(roomsErrorCode==REC_SUCCESS);
  1059. RemoveUserFromQuickJoin(potentialNewRoommates[quickJoinIndex2]->roomsParticipant, &qju);
  1060. dereferencedPointers.Insert(qju, _FILE_AND_LINE_ );
  1061. joinedRoomResult.joiningMember=potentialNewRoommates[quickJoinIndex2]->roomsParticipant;
  1062. joinedRoomMembers.Insert(joinedRoomResult, _FILE_AND_LINE_ );
  1063. }
  1064. joinedRoomResult.joiningMember=quickJoinMember->roomsParticipant;
  1065. joinedRoomMembers.Insert(joinedRoomResult, _FILE_AND_LINE_ );
  1066. RemoveUserFromQuickJoin(quickJoinMember->roomsParticipant, &qju);
  1067. dereferencedPointers.Insert(qju, _FILE_AND_LINE_ );
  1068. continue;
  1069. }
  1070. }
  1071. }
  1072. quickJoinIndex++;
  1073. }
  1074. // 5. Remove from list if timeout has expired.
  1075. quickJoinIndex=0;
  1076. while (quickJoinIndex < quickJoinList.Size())
  1077. {
  1078. if (quickJoinList[quickJoinIndex]->totalTimeWaiting >= quickJoinList[quickJoinIndex]->networkedQuickJoinUser.timeout)
  1079. {
  1080. quickJoinList[quickJoinIndex]->roomsParticipant->SetInQuickJoin(false);
  1081. timeoutExpired.Insert(quickJoinList[quickJoinIndex], _FILE_AND_LINE_ );
  1082. dereferencedPointers.Insert(quickJoinList[quickJoinIndex], _FILE_AND_LINE_ );
  1083. quickJoinList.RemoveAtIndexFast(quickJoinIndex);
  1084. }
  1085. else
  1086. quickJoinIndex++;
  1087. }
  1088. return numRoomsCreated;
  1089. }
  1090. RoomsErrorCode PerGameRoomsContainer::GetInvitesToParticipant(RoomsParticipant* roomsParticipant, DataStructures::List<InvitedUser*> &invites)
  1091. {
  1092. DataStructures::List<Room*> rooms;
  1093. GetAllRooms(rooms);
  1094. unsigned i;
  1095. for (i=0; i < rooms.Size(); i++)
  1096. rooms[i]->GetInvitesToParticipant(roomsParticipant, invites);
  1097. return REC_SUCCESS;
  1098. }
  1099. bool PerGameRoomsContainer::DestroyRoomIfDead(Room *room)
  1100. {
  1101. if (roomsTable.GetRowByID(room->GetID())==room->tableRow)
  1102. {
  1103. roomsTable.RemoveRow(room->GetID());
  1104. delete room;
  1105. return true;
  1106. }
  1107. return false;
  1108. }
  1109. void PerGameRoomsContainer::ChangeHandle(RakNet::RakString oldHandle, RakNet::RakString newHandle)
  1110. {
  1111. DataStructures::List<Room*> rooms;
  1112. GetAllRooms(rooms);
  1113. unsigned i;
  1114. for (i=0; i < rooms.Size(); i++)
  1115. rooms[i]->ChangeHandle(oldHandle, newHandle);
  1116. }
  1117. RoomsErrorCode PerGameRoomsContainer::SearchByFilter( RoomsParticipant* roomsParticipant, RoomQuery *roomQuery, DataStructures::OrderedList<Room*, Room*, AllGamesRoomsContainer::RoomsSortByName> &roomsOutput, bool onlyJoinable )
  1118. {
  1119. DataStructures::Table resultTable;
  1120. unsigned columnIndices[1];
  1121. columnIndices[0]=DefaultRoomColumns::TC_LOBBY_ROOM_PTR;
  1122. // Process user queries
  1123. roomsTable.QueryTable(columnIndices,1,roomQuery->queries,roomQuery->numQueries,0,0,&resultTable);
  1124. roomsOutput.Clear(false, _FILE_AND_LINE_);
  1125. DataStructures::Page<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> *cur = resultTable.GetRows().GetListHead();
  1126. int i;
  1127. Room *room;
  1128. while (cur)
  1129. {
  1130. for (i=0; i < cur->size; i++)
  1131. {
  1132. // Put all the pointers in the roomSort list, filtering out those you cannot join (full, or no public and you are not invited)
  1133. room = (Room*) cur->data[i]->cells[0]->ptr;
  1134. if ( (onlyJoinable==false || room->ParticipantCanJoinRoom(roomsParticipant, false, true)==PCJRR_SUCCESS) &&
  1135. room->IsHiddenToParticipant(roomsParticipant)==false)
  1136. roomsOutput.Insert(room,room,true, _FILE_AND_LINE_ );
  1137. }
  1138. cur=cur->next;
  1139. }
  1140. return REC_SUCCESS;
  1141. }
  1142. void PerGameRoomsContainer::RoomPrioritySort( RoomsParticipant* roomsParticipant, RoomQuery *roomQuery, DataStructures::OrderedList<Room*, Room*, RoomsSortByTimeThenTotalSlots> &roomsOutput )
  1143. {
  1144. int i;
  1145. // If you don't care about room filters, just join any room
  1146. if (roomQuery==0 || roomQuery->numQueries==0 || roomQuery->queries==0)
  1147. {
  1148. DataStructures::List<Room*> rooms;
  1149. GetAllRooms(rooms);
  1150. for (i=0; (unsigned) i < rooms.Size(); i++)
  1151. {
  1152. Room *room = rooms[i];
  1153. if (room->ParticipantCanJoinRoom(roomsParticipant, false, true)==PCJRR_SUCCESS &&
  1154. room->IsHiddenToParticipant(roomsParticipant)==false)
  1155. roomsOutput.Insert(rooms[i], rooms[i], true, _FILE_AND_LINE_ );
  1156. }
  1157. return;
  1158. }
  1159. // Must pass room query
  1160. // Of those that pass room query, sort by time (lower is first). If within one minute of each other, sort by number of users in playable slots (higher if first)
  1161. // Be sure to return columns TC_LOBBY_ROOM_PTR, TC_USED_PUBLIC_PLUS_RESERVED_SLOTS, TC_LOBBY_ROOM_PTR
  1162. DataStructures::Table resultTable;
  1163. unsigned columnIndices[1];
  1164. columnIndices[0]=DefaultRoomColumns::TC_LOBBY_ROOM_PTR;
  1165. // Process user queries
  1166. roomsTable.QueryTable(columnIndices,1,roomQuery->queries,roomQuery->numQueries,0,0,&resultTable);
  1167. roomsOutput.Clear(false, _FILE_AND_LINE_);
  1168. DataStructures::Page<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> *cur = resultTable.GetRows().GetListHead();
  1169. Room *room;
  1170. while (cur)
  1171. {
  1172. for (i=0; i < cur->size; i++)
  1173. {
  1174. // Put all the pointers in the roomSort list, filtering out those you cannot join (full, or no public and you are not invited)
  1175. room = (Room*) cur->data[i]->cells[0]->ptr;
  1176. if (room->ParticipantCanJoinRoom(roomsParticipant, false, true)==PCJRR_SUCCESS &&
  1177. room->IsHiddenToParticipant(roomsParticipant)==false)
  1178. roomsOutput.Insert(room,room,true, _FILE_AND_LINE_ );
  1179. }
  1180. cur=cur->next;
  1181. }
  1182. }
  1183. Room* PerGameRoomsContainer::GetRoomByLobbyRoomID(RoomID lobbyRoomID)
  1184. {
  1185. DataStructures::Table::Row *row = roomsTable.GetRowByID(lobbyRoomID);
  1186. if (row==0)
  1187. return 0;
  1188. return (Room*) roomsTable.GetRowByID(lobbyRoomID)->cells[DefaultRoomColumns::TC_LOBBY_ROOM_PTR]->ptr;
  1189. }
  1190. Room * PerGameRoomsContainer::GetRoomByName(RakNet::RakString roomName)
  1191. {
  1192. DataStructures::List<Room*> rooms;
  1193. GetAllRooms(rooms);
  1194. unsigned int i;
  1195. for (i=0; i < rooms.Size(); i++)
  1196. {
  1197. if (strcmp(rooms[i]->GetStringProperty(DefaultRoomColumns::TC_ROOM_NAME), roomName.C_String())==0)
  1198. {
  1199. return rooms[i];
  1200. }
  1201. }
  1202. return 0;
  1203. }
  1204. void PerGameRoomsContainer::GetAllRooms(DataStructures::List<Room*> &rooms)
  1205. {
  1206. DataStructures::Page<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> *cur = roomsTable.GetRows().GetListHead();
  1207. int i;
  1208. rooms.Clear(false, _FILE_AND_LINE_);
  1209. while (cur)
  1210. {
  1211. for (i=0; i < cur->size; i++)
  1212. rooms.Insert((Room*)cur->data[i]->cells[DefaultRoomColumns::TC_LOBBY_ROOM_PTR]->ptr, _FILE_AND_LINE_ );
  1213. cur=cur->next;
  1214. }
  1215. }
  1216. void PerGameRoomsContainer::GetRoomNames(DataStructures::List<RakNet::RakString> &roomNames)
  1217. {
  1218. DataStructures::Page<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> *cur = roomsTable.GetRows().GetListHead();
  1219. int i;
  1220. roomNames.Clear(false, _FILE_AND_LINE_);
  1221. while (cur)
  1222. {
  1223. for (i=0; i < cur->size; i++)
  1224. roomNames.Insert(RakNet::RakString(cur->data[i]->cells[DefaultRoomColumns::TC_ROOM_NAME]->c), _FILE_AND_LINE_ );
  1225. cur=cur->next;
  1226. }
  1227. }
  1228. unsigned int PerGameRoomsContainer::GetQuickJoinIndex(RoomsParticipant* roomsParticipant)
  1229. {
  1230. unsigned int i;
  1231. for (i=0; i < quickJoinList.Size(); i++)
  1232. if (quickJoinList[i]->roomsParticipant==roomsParticipant)
  1233. return i;
  1234. return (unsigned int) -1;
  1235. }
  1236. // ---------------------------- ROOMS ----------------------------
  1237. Room::Room( RoomID _roomId, RoomCreationParameters *roomCreationParameters, DataStructures::Table::Row *_row, RoomsParticipant* roomsParticipant )
  1238. {
  1239. roomDestroyed=false;
  1240. lobbyRoomId=_roomId;
  1241. tableRow=_row;
  1242. autoLockReadyStatus=roomCreationParameters->networkedRoomCreationParameters.autoLockReadyStatus;
  1243. hiddenFromSearches=roomCreationParameters->networkedRoomCreationParameters.hiddenFromSearches;
  1244. // destroyOnModeratorLeave=roomCreationParameters->networkedRoomCreationParameters.destroyOnModeratorLeave;
  1245. clearInvitesOnNewModerator=roomCreationParameters->networkedRoomCreationParameters.clearInvitesOnNewModerator;
  1246. inviteToRoomPermission=roomCreationParameters->networkedRoomCreationParameters.inviteToRoomPermission;
  1247. inviteToSpectatorSlotPermission=roomCreationParameters->networkedRoomCreationParameters.inviteToSpectatorSlotPermission;
  1248. roomLockState=RLS_NOT_LOCKED;
  1249. Slots usedSlots;
  1250. UpdateRowSlots( tableRow, &roomCreationParameters->networkedRoomCreationParameters.slots, &usedSlots);
  1251. RoomMember *roomMember = new RoomMember;
  1252. roomMember->roomMemberMode=RMM_MODERATOR;
  1253. roomMember->roomsParticipant=roomsParticipant;
  1254. roomsParticipant->SetRoom(this);
  1255. roomMemberList.Insert(roomMember, _FILE_AND_LINE_ );
  1256. tableRow->cells[DefaultRoomColumns::TC_ROOM_NAME]->Set(roomCreationParameters->networkedRoomCreationParameters.roomName.C_String());
  1257. tableRow->cells[DefaultRoomColumns::TC_ROOM_ID]->Set(lobbyRoomId);
  1258. tableRow->cells[DefaultRoomColumns::TC_CREATION_TIME]->Set((int) RakNet::GetTimeMS());
  1259. tableRow->cells[DefaultRoomColumns::TC_DESTROY_ON_MODERATOR_LEAVE]->Set((int) roomCreationParameters->networkedRoomCreationParameters.destroyOnModeratorLeave);
  1260. tableRow->cells[DefaultRoomColumns::TC_LOBBY_ROOM_PTR]->SetPtr(this);
  1261. }
  1262. Room::~Room()
  1263. {
  1264. }
  1265. void Room::UpdateRowSlots( DataStructures::Table::Row* row, Slots *totalSlots, Slots *usedSlots)
  1266. {
  1267. row->cells[DefaultRoomColumns::TC_TOTAL_SLOTS]->Set(totalSlots->publicSlots+totalSlots->reservedSlots+totalSlots->spectatorSlots);
  1268. row->cells[DefaultRoomColumns::TC_TOTAL_PUBLIC_PLUS_RESERVED_SLOTS]->Set(totalSlots->publicSlots+totalSlots->reservedSlots);
  1269. row->cells[DefaultRoomColumns::TC_TOTAL_PUBLIC_SLOTS]->Set(totalSlots->publicSlots);
  1270. row->cells[DefaultRoomColumns::TC_TOTAL_RESERVED_SLOTS]->Set(totalSlots->reservedSlots);
  1271. row->cells[DefaultRoomColumns::TC_TOTAL_SPECTATOR_SLOTS]->Set(totalSlots->spectatorSlots);
  1272. UpdateUsedSlots(row, totalSlots, usedSlots);
  1273. }
  1274. void Room::UpdateUsedSlots( void )
  1275. {
  1276. Slots totalSlots = GetTotalSlots();
  1277. Slots usedSlots = GetUsedSlots();
  1278. UpdateUsedSlots(&totalSlots, &usedSlots);
  1279. }
  1280. void Room::UpdateUsedSlots( DataStructures::Table::Row* tableRow, Slots *totalSlots, Slots *usedSlots )
  1281. {
  1282. tableRow->cells[DefaultRoomColumns::TC_USED_SLOTS]->Set(usedSlots->publicSlots+usedSlots->reservedSlots+usedSlots->spectatorSlots);
  1283. tableRow->cells[DefaultRoomColumns::TC_USED_PUBLIC_PLUS_RESERVED_SLOTS]->Set(usedSlots->publicSlots+usedSlots->reservedSlots);
  1284. tableRow->cells[DefaultRoomColumns::TC_REMAINING_SLOTS]->Set(totalSlots->publicSlots+totalSlots->reservedSlots+totalSlots->spectatorSlots-usedSlots->publicSlots-usedSlots->reservedSlots-usedSlots->spectatorSlots);
  1285. tableRow->cells[DefaultRoomColumns::TC_REMAINING_PUBLIC_PLUS_RESERVED_SLOTS]->Set(totalSlots->publicSlots+totalSlots->reservedSlots-usedSlots->publicSlots-usedSlots->reservedSlots);
  1286. tableRow->cells[DefaultRoomColumns::TC_USED_PUBLIC_SLOTS]->Set(usedSlots->publicSlots);
  1287. tableRow->cells[DefaultRoomColumns::TC_USED_RESERVED_SLOTS]->Set(usedSlots->reservedSlots);
  1288. tableRow->cells[DefaultRoomColumns::TC_USED_SPECTATOR_SLOTS]->Set(usedSlots->spectatorSlots);
  1289. tableRow->cells[DefaultRoomColumns::TC_REMAINING_PUBLIC_SLOTS]->Set(totalSlots->publicSlots-usedSlots->publicSlots);
  1290. tableRow->cells[DefaultRoomColumns::TC_REMAINING_RESERVED_SLOTS]->Set(totalSlots->reservedSlots-usedSlots->reservedSlots);
  1291. tableRow->cells[DefaultRoomColumns::TC_REMAINING_SPECTATOR_SLOTS]->Set(totalSlots->spectatorSlots-usedSlots->spectatorSlots);
  1292. }
  1293. void Room::UpdateUsedSlots( Slots *totalSlots, Slots *usedSlots )
  1294. {
  1295. UpdateUsedSlots(tableRow, totalSlots, usedSlots);
  1296. }
  1297. Slots Room::GetTotalSlots(void) const
  1298. {
  1299. Slots totalSlots;
  1300. totalSlots.publicSlots=(int)GetNumericProperty(DefaultRoomColumns::TC_TOTAL_PUBLIC_SLOTS);
  1301. totalSlots.reservedSlots=(int)GetNumericProperty(DefaultRoomColumns::TC_TOTAL_RESERVED_SLOTS);
  1302. totalSlots.spectatorSlots=(int)GetNumericProperty(DefaultRoomColumns::TC_TOTAL_SPECTATOR_SLOTS);
  1303. return totalSlots;
  1304. }
  1305. void Room::SetTotalSlots(Slots *totalSlots)
  1306. {
  1307. SetNumericProperty(DefaultRoomColumns::TC_TOTAL_PUBLIC_SLOTS, totalSlots->publicSlots);
  1308. SetNumericProperty(DefaultRoomColumns::TC_TOTAL_RESERVED_SLOTS, totalSlots->reservedSlots);
  1309. SetNumericProperty(DefaultRoomColumns::TC_TOTAL_SPECTATOR_SLOTS, totalSlots->spectatorSlots);
  1310. }
  1311. Slots Room::GetUsedSlots(void) const
  1312. {
  1313. Slots usedSlots;
  1314. unsigned i;
  1315. for (i=0; i < roomMemberList.Size(); i++)
  1316. {
  1317. if (roomMemberList[i]->roomMemberMode==RMM_PUBLIC)
  1318. usedSlots.publicSlots++;
  1319. else if (roomMemberList[i]->roomMemberMode==RMM_RESERVED)
  1320. usedSlots.reservedSlots++;
  1321. else if (
  1322. roomMemberList[i]->roomMemberMode==RMM_SPECTATOR_PUBLIC ||
  1323. roomMemberList[i]->roomMemberMode==RMM_SPECTATOR_RESERVED)
  1324. usedSlots.spectatorSlots++;
  1325. // Moderator not counted
  1326. }
  1327. return usedSlots;
  1328. }
  1329. RoomsErrorCode Room::SendInvite(RoomsParticipant* roomsParticipant, RoomsParticipant* inviteeId, bool inviteToSpectatorSlot, RakNet::RakString subject, RakNet::RakString body)
  1330. {
  1331. RakAssert(roomDestroyed==false);
  1332. // Is roomsParticipant in the room?
  1333. unsigned int roomsParticipantIndex = GetRoomIndex(roomsParticipant);
  1334. if (roomsParticipantIndex==-1) return REC_SEND_INVITE_INVITOR_NOT_IN_ROOM;
  1335. if (roomsParticipant==inviteeId)
  1336. return REC_SEND_INVITE_CANNOT_PERFORM_ON_SELF;
  1337. // Is inviteeId not in the room?
  1338. if (IsInRoom(inviteeId)) return REC_SEND_INVITE_INVITEE_ALREADY_IN_THIS_ROOM;
  1339. // Does inviteeId already have an invite from roomsParticipant (either slot type)?
  1340. if (HasInvite(inviteeId->GetName())) return REC_SEND_INVITE_INVITEE_ALREADY_INVITED;
  1341. // Can inviteeId join?
  1342. ParticipantCanJoinRoomResult pcjrr = ParticipantCanJoinRoom(inviteeId, inviteToSpectatorSlot, false);
  1343. if (pcjrr==PCJRR_BANNED) return REC_SEND_INVITE_INVITEE_BANNED;
  1344. if (pcjrr==PCJRR_NO_PUBLIC_SLOTS && inviteToSpectatorSlot==false) return REC_SEND_INVITE_NO_SLOTS;
  1345. if (pcjrr==PCJRR_NO_PUBLIC_OR_RESERVED_SLOTS) return REC_SEND_INVITE_NO_SLOTS;
  1346. if (pcjrr==PCJRR_LOCKED) return REC_SEND_INVITE_ROOM_LOCKED;
  1347. RakAssert(pcjrr==PCJRR_SUCCESS);
  1348. // Can roomsParticipant send an invite, given inviteToRoomPermission or inviteToSpectatorSlotPermission? (leader can always invite no matter what)
  1349. RoomMemberMode memberMode = roomMemberList[roomsParticipantIndex]->roomMemberMode;
  1350. RakAssert(memberMode!=RMM_ANY_PLAYABLE);
  1351. bool canInvite;
  1352. if (memberMode==RMM_MODERATOR)
  1353. {
  1354. canInvite=true;
  1355. }
  1356. else
  1357. {
  1358. NetworkedRoomCreationParameters::SendInvitePermission relevantPermission;
  1359. if (inviteToSpectatorSlotPermission)
  1360. relevantPermission=inviteToSpectatorSlotPermission;
  1361. else
  1362. relevantPermission=inviteToRoomPermission;
  1363. if (relevantPermission==NetworkedRoomCreationParameters::INVITE_MODE_MODERATOR_CAN_INVITE)
  1364. return REC_SEND_INVITE_INVITOR_ONLY_MODERATOR_CAN_INVITE;
  1365. if (relevantPermission==NetworkedRoomCreationParameters::INVITE_MODE_ANYONE_CAN_INVITE)
  1366. canInvite=true;
  1367. else if (
  1368. (relevantPermission==NetworkedRoomCreationParameters::INVITE_MODE_PUBLIC_SLOTS_CAN_INVITE ||
  1369. relevantPermission==NetworkedRoomCreationParameters::INVITE_MODE_MODERATOR_OR_PUBLIC_SLOTS_CAN_INVITE ||
  1370. relevantPermission==NetworkedRoomCreationParameters::INVITE_MODE_MODERATOR_OR_PUBLIC_OR_RESERVED_SLOTS_CAN_INVITE)
  1371. && memberMode==RMM_PUBLIC)
  1372. canInvite=true;
  1373. else if (
  1374. (relevantPermission==NetworkedRoomCreationParameters::INVITE_MODE_RESERVED_SLOTS_CAN_INVITE ||
  1375. relevantPermission==NetworkedRoomCreationParameters::INVITE_MODE_MODERATOR_OR_PUBLIC_OR_RESERVED_SLOTS_CAN_INVITE)
  1376. && memberMode==RMM_RESERVED)
  1377. canInvite=true;
  1378. else if (relevantPermission==NetworkedRoomCreationParameters::INVITE_MODE_SPECTATOR_SLOTS_CAN_INVITE && (memberMode==RMM_SPECTATOR_PUBLIC || memberMode==RMM_SPECTATOR_RESERVED))
  1379. canInvite=true;
  1380. else if (relevantPermission==NetworkedRoomCreationParameters::INVITE_MODE_MODERATOR_OR_PUBLIC_SLOTS_CAN_INVITE && (memberMode==RMM_SPECTATOR_PUBLIC || memberMode==RMM_SPECTATOR_RESERVED))
  1381. canInvite=true;
  1382. else
  1383. return REC_SEND_INVITE_INVITOR_LACK_INVITE_PERMISSIONS;
  1384. }
  1385. InvitedUser invitedUser;
  1386. invitedUser.body=body;
  1387. invitedUser.invitedAsSpectator=inviteToSpectatorSlot;
  1388. invitedUser.target=inviteeId->GetName();
  1389. invitedUser.invitorName=roomsParticipant->GetName();
  1390. invitedUser.room=this;
  1391. invitedUser.subject=subject;
  1392. inviteList.Insert(invitedUser, _FILE_AND_LINE_ );
  1393. return REC_SUCCESS;
  1394. }
  1395. RoomsErrorCode Room::AcceptInvite(RoomsParticipant* roomsParticipant, RakNet::RakString inviteSender)
  1396. {
  1397. RakAssert(roomDestroyed==false);
  1398. // Is roomsParticipant not in the roomOutput?
  1399. unsigned int roomsParticipantIndex = GetRoomIndex(roomsParticipant);
  1400. if (roomsParticipantIndex!=-1) return REC_ACCEPT_INVITE_CURRENTLY_IN_A_ROOM;
  1401. // Does roomsParticipant have an invite from inviteSender?
  1402. unsigned int inviteIndex = GetInviteIndex(roomsParticipant->GetName(), inviteSender);
  1403. if (inviteIndex==-1) return REC_ACCEPT_INVITE_NO_SUCH_INVITE;
  1404. // Is the roomOutput locked for the target slot type (any slot and RLS_ALL_LOCKED, or player and RLS_PLAYERS_LOCKED)?
  1405. ParticipantCanJoinRoomResult pcjrr = ParticipantCanJoinRoom(roomsParticipant, inviteList[inviteIndex].invitedAsSpectator, true);
  1406. if (pcjrr==PCJRR_BANNED) return REC_ACCEPT_INVITE_BANNED;
  1407. if (pcjrr==PCJRR_NO_PUBLIC_SLOTS || pcjrr==PCJRR_NO_PUBLIC_OR_RESERVED_SLOTS) return REC_ACCEPT_INVITE_NO_SLOTS;
  1408. if (pcjrr==PCJRR_LOCKED) return REC_ACCEPT_INVITE_ROOM_LOCKED;
  1409. RakAssert(pcjrr==PCJRR_SUCCESS);
  1410. // Remove the used invite
  1411. inviteList.RemoveAtIndex(inviteIndex);
  1412. // Add the new roomOutput member
  1413. RoomMember* roomMember = new RoomMember;
  1414. roomMember->isReady=false;
  1415. roomMember->joinTime=RakNet::GetTimeMS();
  1416. roomMember->roomMemberMode=RMM_RESERVED;
  1417. roomMember->roomsParticipant=roomsParticipant;
  1418. roomsParticipant->SetRoom(this);
  1419. roomMemberList.Insert(roomMember, _FILE_AND_LINE_ );
  1420. UpdateUsedSlots();
  1421. return REC_SUCCESS;
  1422. }
  1423. RoomsErrorCode Room::StartSpectating(RoomsParticipant* roomsParticipant)
  1424. {
  1425. RakAssert(roomDestroyed==false);
  1426. // Is roomsParticipant in the roomOutput?
  1427. unsigned int roomsParticipantIndex = GetRoomIndex(roomsParticipant);
  1428. if (roomsParticipantIndex==-1) return REC_START_SPECTATING_NOT_IN_ROOM;
  1429. // Is roomsParticipant the moderator? Moderator must grant moderator to another user first
  1430. // Would this destroy the roomOutput (no players left)? (last player is always leader)
  1431. if (roomMemberList[roomsParticipantIndex]->roomMemberMode==RMM_MODERATOR)
  1432. return REC_START_SPECTATING_REASSIGN_MODERATOR_BEFORE_SPECTATE;
  1433. // Already spectating?
  1434. if (roomMemberList[roomsParticipantIndex]->roomMemberMode==RMM_SPECTATOR_PUBLIC ||
  1435. roomMemberList[roomsParticipantIndex]->roomMemberMode==RMM_SPECTATOR_RESERVED)
  1436. return REC_START_SPECTATING_ALREADY_SPECTATING;
  1437. // Are there open spectator slots?
  1438. if (GetNumericProperty(DefaultRoomColumns::TC_REMAINING_SPECTATOR_SLOTS)<=0.0)
  1439. return REC_START_SPECTATING_NO_SPECTATOR_SLOTS_AVAILABLE;
  1440. // Is the roomOutput locked to spectators (RLS_ALL_LOCKED)?
  1441. if (roomLockState==RLS_ALL_LOCKED)
  1442. return REC_START_SPECTATING_ROOM_LOCKED;
  1443. if (roomMemberList[roomsParticipantIndex]->roomMemberMode==RMM_RESERVED ||
  1444. roomMemberList[roomsParticipantIndex]->roomMemberMode==RMM_MODERATOR)
  1445. roomMemberList[roomsParticipantIndex]->roomMemberMode=RMM_SPECTATOR_RESERVED;
  1446. else
  1447. roomMemberList[roomsParticipantIndex]->roomMemberMode=RMM_SPECTATOR_PUBLIC;
  1448. UpdateUsedSlots();
  1449. return REC_SUCCESS;
  1450. }
  1451. RoomsErrorCode Room::StopSpectating(RoomsParticipant* roomsParticipant)
  1452. {
  1453. RakAssert(roomDestroyed==false);
  1454. // Is roomsParticipant a spectator?
  1455. unsigned int roomsParticipantIndex = GetRoomIndex(roomsParticipant);
  1456. if (roomsParticipantIndex==-1) return REC_STOP_SPECTATING_NOT_IN_ROOM;
  1457. if (roomMemberList[roomsParticipantIndex]->roomMemberMode!=RMM_SPECTATOR_PUBLIC &&
  1458. roomMemberList[roomsParticipantIndex]->roomMemberMode!=RMM_SPECTATOR_RESERVED)
  1459. return REC_STOP_SPECTATING_NOT_CURRENTLY_SPECTATING;
  1460. // Is the roomOutput locked to players (RLS_ALL_LOCKED or RLS_PLAYERS_LOCKED)?
  1461. ParticipantCanJoinRoomResult pcjrr = ParticipantCanJoinAsPlayer(roomsParticipant, false, true);
  1462. RakAssert(pcjrr!=PCJRR_BANNED);
  1463. if (pcjrr==PCJRR_NO_PUBLIC_OR_RESERVED_SLOTS) return REC_STOP_SPECTATING_NO_SLOTS;
  1464. if (pcjrr==PCJRR_LOCKED) return REC_STOP_SPECTATING_ROOM_LOCKED;
  1465. RakAssert(pcjrr==PCJRR_SUCCESS);
  1466. if (roomMemberList[roomsParticipantIndex]->roomMemberMode==RMM_SPECTATOR_RESERVED && HasOpenReservedSlots())
  1467. roomMemberList[roomsParticipantIndex]->roomMemberMode=RMM_RESERVED;
  1468. else
  1469. roomMemberList[roomsParticipantIndex]->roomMemberMode=RMM_PUBLIC;
  1470. UpdateUsedSlots();
  1471. return REC_SUCCESS;
  1472. }
  1473. RoomsErrorCode Room::GrantModerator(RoomsParticipant* roomsParticipant, RoomsParticipant *newModerator, DataStructures::List<InvitedUser> &clearedInvites)
  1474. {
  1475. RakAssert(roomDestroyed==false);
  1476. // Is roomsParticipant in the roomOutput?
  1477. unsigned int roomsParticipantIndex = GetRoomIndex(roomsParticipant);
  1478. if (roomsParticipantIndex==-1) return REC_GRANT_MODERATOR_NOT_IN_ROOM;
  1479. // Is roomsParticipant the moderator?
  1480. if (roomMemberList[roomsParticipantIndex]->roomMemberMode!=RMM_MODERATOR)
  1481. return REC_GRANT_MODERATOR_MUST_BE_MODERATOR_TO_GRANT_MODERATOR;
  1482. // Is newModerator in the roomOutput as a player?
  1483. unsigned int newModeratorIndex = GetRoomIndex(newModerator);
  1484. if (newModeratorIndex==-1) return REC_GRANT_MODERATOR_NEW_MODERATOR_NOT_IN_ROOM;
  1485. if (roomMemberList[newModeratorIndex]->roomMemberMode==RMM_SPECTATOR_PUBLIC ||
  1486. roomMemberList[newModeratorIndex]->roomMemberMode==RMM_SPECTATOR_RESERVED)
  1487. return REC_GRANT_MODERATOR_NEW_MODERATOR_NOT_IN_PLAYABLE_SLOT;
  1488. if (roomsParticipant==newModerator)
  1489. return REC_GRANT_MODERATOR_CANNOT_PERFORM_ON_SELF;
  1490. if (clearInvitesOnNewModerator)
  1491. {
  1492. // Clear invites
  1493. clearedInvites=inviteList;
  1494. inviteList.Clear(true, _FILE_AND_LINE_ );
  1495. // Change RMM_SPECTATOR_RESERVED to RMM_SPECTATOR_PUBLIC
  1496. unsigned int i;
  1497. for (i=0; i < roomMemberList.Size(); i++)
  1498. {
  1499. if (roomMemberList[i]->roomMemberMode==RMM_SPECTATOR_RESERVED)
  1500. roomMemberList[i]->roomMemberMode=RMM_SPECTATOR_PUBLIC;
  1501. }
  1502. }
  1503. roomMemberList[roomsParticipantIndex]->roomMemberMode=roomMemberList[newModeratorIndex]->roomMemberMode;
  1504. roomMemberList[newModeratorIndex]->roomMemberMode=RMM_MODERATOR;
  1505. UpdateUsedSlots();
  1506. return REC_SUCCESS;
  1507. }
  1508. RoomsErrorCode Room::ChangeSlotCounts(RoomsParticipant* roomsParticipant, Slots slots)
  1509. {
  1510. RakAssert(roomDestroyed==false);
  1511. // Is roomsParticipant in the roomOutput?
  1512. unsigned int roomsParticipantIndex = GetRoomIndex(roomsParticipant);
  1513. if (roomsParticipantIndex==-1) return REC_CHANGE_SLOT_COUNTS_NOT_IN_ROOM;
  1514. // Is roomsParticipant the moderator?
  1515. if (roomMemberList[roomsParticipantIndex]->roomMemberMode!=RMM_MODERATOR)
  1516. return REC_CHANGE_SLOT_COUNTS_MUST_BE_MODERATOR;
  1517. // Validate slots - cannot be negative
  1518. RoomsErrorCode roomsErrorCode = slots.Validate();
  1519. if (roomsErrorCode!=REC_SUCCESS)
  1520. return roomsErrorCode;
  1521. SetTotalSlots(&slots);
  1522. UpdateUsedSlots();
  1523. return REC_SUCCESS;
  1524. }
  1525. RoomsErrorCode Room::SetCustomRoomProperties(RoomsParticipant* roomsParticipant, DataStructures::Table *table)
  1526. {
  1527. RakAssert(roomDestroyed==false);
  1528. // Is roomsParticipant in the roomOutput?
  1529. unsigned int roomsParticipantIndex = GetRoomIndex(roomsParticipant);
  1530. if (roomsParticipantIndex==-1) return REC_SET_CUSTOM_ROOM_PROPERTIES_NOT_IN_ROOM;
  1531. // Is roomsParticipant the moderator?
  1532. if (roomMemberList[roomsParticipantIndex]->roomMemberMode!=RMM_MODERATOR)
  1533. return REC_SET_CUSTOM_ROOM_PROPERTIES_MUST_BE_MODERATOR;
  1534. // Validate table - can only have custom properties, not predefined properties
  1535. if (DefaultRoomColumns::HasDefaultColumns(table))
  1536. return REC_SET_CUSTOM_ROOM_PROPERTIES_CONTAINS_DEFAULT_COLUMNS;
  1537. return REC_SUCCESS;
  1538. }
  1539. RoomsErrorCode Room::ChangeRoomName(RoomsParticipant* roomsParticipant, RakNet::RakString newRoomName, ProfanityFilter *profanityFilter)
  1540. {
  1541. RakAssert(roomDestroyed==false);
  1542. // Is roomsParticipant in the roomOutput?
  1543. unsigned int roomsParticipantIndex = GetRoomIndex(roomsParticipant);
  1544. if (roomsParticipantIndex==-1) return REC_CHANGE_ROOM_NAME_NOT_IN_ROOM;
  1545. // Is roomsParticipant the moderator?
  1546. if (roomMemberList[roomsParticipantIndex]->roomMemberMode!=RMM_MODERATOR)
  1547. return REC_CHANGE_ROOM_NAME_MUST_BE_MODERATOR;
  1548. // Is newRoomName empty?
  1549. if (newRoomName.IsEmpty())
  1550. return REC_CHANGE_ROOM_NAME_EMPTY_ROOM_NAME;
  1551. // Does newRoomName have profanity?
  1552. if (profanityFilter->HasProfanity(newRoomName.C_String()))
  1553. return REC_CHANGE_ROOM_NAME_HAS_PROFANITY;
  1554. SetStringProperty(DefaultRoomColumns::TC_ROOM_NAME, newRoomName.C_String());
  1555. return REC_SUCCESS;
  1556. }
  1557. RoomsErrorCode Room::SetHiddenFromSearches(RoomsParticipant* roomsParticipant, bool _hiddenFromSearches)
  1558. {
  1559. RakAssert(roomDestroyed==false);
  1560. // Is roomsParticipant in the roomOutput?
  1561. unsigned int roomsParticipantIndex = GetRoomIndex(roomsParticipant);
  1562. if (roomsParticipantIndex==-1) return REC_SET_HIDDEN_FROM_SEARCHES_NOT_IN_ROOM;
  1563. // Is roomsParticipant the moderator?
  1564. if (roomMemberList[roomsParticipantIndex]->roomMemberMode!=RMM_MODERATOR)
  1565. return REC_SET_HIDDEN_FROM_SEARCHES_MUST_BE_MODERATOR;
  1566. hiddenFromSearches=_hiddenFromSearches;
  1567. return REC_SUCCESS;
  1568. }
  1569. RoomsErrorCode Room::SetDestroyOnModeratorLeave(RoomsParticipant* roomsParticipant, bool destroyOnModeratorLeave)
  1570. {
  1571. RakAssert(roomDestroyed==false);
  1572. // Is roomsParticipant in the roomOutput?
  1573. unsigned int roomsParticipantIndex = GetRoomIndex(roomsParticipant);
  1574. if (roomsParticipantIndex==-1) return REC_SET_DESTROY_ON_MODERATOR_LEAVE_NOT_IN_ROOM;
  1575. // Is roomsParticipant the moderator?
  1576. if (roomMemberList[roomsParticipantIndex]->roomMemberMode!=RMM_MODERATOR)
  1577. return REC_SET_DESTROY_ON_MODERATOR_LEAVE_MUST_BE_MODERATOR;
  1578. tableRow->cells[DefaultRoomColumns::TC_DESTROY_ON_MODERATOR_LEAVE]->Set((int) destroyOnModeratorLeave);
  1579. return REC_SUCCESS;
  1580. }
  1581. RoomsErrorCode Room::SetReadyStatus(RoomsParticipant* roomsParticipant, bool isReady)
  1582. {
  1583. RakAssert(roomDestroyed==false);
  1584. // Is roomsParticipant in the roomOutput?
  1585. unsigned int roomsParticipantIndex = GetRoomIndex(roomsParticipant);
  1586. if (roomsParticipantIndex==-1) return REC_SET_READY_STATUS_NOT_IN_ROOM;
  1587. // Is roomsParticipant a player?
  1588. if (roomMemberList[roomsParticipantIndex]->roomMemberMode!=RMM_MODERATOR &&
  1589. roomMemberList[roomsParticipantIndex]->roomMemberMode!=RMM_PUBLIC &&
  1590. roomMemberList[roomsParticipantIndex]->roomMemberMode!=RMM_RESERVED)
  1591. return REC_SET_READY_STATUS_NOT_IN_PLAYABLE_SLOT;
  1592. // Is autoLockReadyStatus true, the roomOutput locked or the roomOutput full of players, and all the other players are ready?
  1593. bool allReady;
  1594. AreAllMembersReady(roomsParticipantIndex,&allReady);
  1595. if (autoLockReadyStatus==true &&
  1596. isReady==false &&
  1597. (AreAllPlayableSlotsFilled() || IsRoomLockedToPlayers()) &&
  1598. allReady)
  1599. return REC_SET_READY_STATUS_AUTO_LOCK_ALL_PLAYERS_READY;
  1600. roomMemberList[roomsParticipantIndex]->isReady=isReady;
  1601. return REC_SUCCESS;
  1602. }
  1603. RoomsErrorCode Room::GetReadyStatus(DataStructures::List<RoomsParticipant*> &readyUsers, DataStructures::List<RoomsParticipant*> &unreadyUsers)
  1604. {
  1605. RakAssert(roomDestroyed==false);
  1606. readyUsers.Clear(true, _FILE_AND_LINE_ );
  1607. unreadyUsers.Clear(true, _FILE_AND_LINE_ );
  1608. unsigned int i;
  1609. for (i=0; i < roomMemberList.Size(); i++)
  1610. {
  1611. if (roomMemberList[i]->isReady)
  1612. readyUsers.Insert(roomMemberList[i]->roomsParticipant, _FILE_AND_LINE_ );
  1613. else
  1614. unreadyUsers.Insert(roomMemberList[i]->roomsParticipant, _FILE_AND_LINE_ );
  1615. }
  1616. return REC_SUCCESS;
  1617. }
  1618. RoomsErrorCode Room::SetRoomLockState(RoomsParticipant* roomsParticipant, RoomLockState _roomLockState)
  1619. {
  1620. RakAssert(roomDestroyed==false);
  1621. // Is roomsParticipant in the roomOutput?
  1622. unsigned int roomsParticipantIndex = GetRoomIndex(roomsParticipant);
  1623. if (roomsParticipantIndex==-1) return REC_SET_ROOM_LOCK_STATE_NOT_IN_ROOM;
  1624. // Is roomsParticipant the moderator?
  1625. if (roomMemberList[roomsParticipantIndex]->roomMemberMode!=RMM_MODERATOR)
  1626. return REC_SET_ROOM_LOCK_STATE_MUST_BE_MODERATOR;
  1627. // Is roomLockState a valid enumeration value?
  1628. if ((int)roomLockState<0 || (int)roomLockState>(int)RLS_ALL_LOCKED)
  1629. return REC_SET_ROOM_LOCK_STATE_BAD_ENUMERATION_VALUE;
  1630. roomLockState=_roomLockState;
  1631. return REC_SUCCESS;
  1632. }
  1633. RoomsErrorCode Room::GetRoomLockState(RoomLockState *_roomLockState)
  1634. {
  1635. RakAssert(roomDestroyed==false);
  1636. *_roomLockState=roomLockState;
  1637. return REC_SUCCESS;
  1638. }
  1639. RoomsErrorCode Room::AreAllMembersReady(unsigned int exceptThisIndex, bool *allReady)
  1640. {
  1641. RakAssert(roomDestroyed==false);
  1642. // Is the ready status for all members true?
  1643. unsigned int i;
  1644. for (i=0; i < roomMemberList.Size(); i++)
  1645. {
  1646. if (roomMemberList[i]->isReady==false && i!=exceptThisIndex)
  1647. {
  1648. *allReady=false;
  1649. return REC_SUCCESS;
  1650. }
  1651. }
  1652. *allReady=true;
  1653. return REC_SUCCESS;
  1654. }
  1655. RoomsErrorCode Room::KickMember(RoomsParticipant* roomsParticipant, RoomsParticipant *kickedParticipant, RakNet::RakString reason )
  1656. {
  1657. RakAssert(roomDestroyed==false);
  1658. // Is roomsParticipant in the roomOutput?
  1659. unsigned int roomsParticipantIndex = GetRoomIndex(roomsParticipant);
  1660. if (roomsParticipantIndex==-1) return REC_KICK_MEMBER_NOT_IN_ROOM;
  1661. // Is roomsParticipant the moderator?
  1662. if (roomMemberList[roomsParticipantIndex]->roomMemberMode!=RMM_MODERATOR)
  1663. return REC_KICK_MEMBER_MUST_BE_MODERATOR;
  1664. // Is kickedParticipant in the roomOutput, or in a spectator slot?
  1665. unsigned int kickedParticipantIndex = GetRoomIndex(kickedParticipant);
  1666. if (kickedParticipantIndex==-1) return REC_KICK_MEMBER_TARGET_NOT_IN_YOUR_ROOM;
  1667. if (roomsParticipant==kickedParticipant)
  1668. return REC_KICK_MEMBER_CANNOT_PERFORM_ON_SELF;
  1669. kickedParticipant->SetRoom(0);
  1670. roomMemberList.RemoveAtIndex(kickedParticipantIndex);
  1671. if (GetBannedIndex(kickedParticipant->GetName())==-1)
  1672. {
  1673. BannedUser bannedUser;
  1674. bannedUser.reason=reason;
  1675. bannedUser.target=kickedParticipant->GetName();
  1676. banList.Insert(bannedUser, _FILE_AND_LINE_ );
  1677. }
  1678. return REC_SUCCESS;
  1679. }
  1680. RoomsErrorCode Room::UnbanMember(RoomsParticipant* roomsParticipant, RakNet::RakString name)
  1681. {
  1682. RakAssert(roomDestroyed==false);
  1683. // Is roomsParticipant in the roomOutput?
  1684. unsigned int roomsParticipantIndex = GetRoomIndex(roomsParticipant);
  1685. if (roomsParticipantIndex==-1) return REC_UNBAN_MEMBER_NOT_IN_ROOM;
  1686. // Is roomsParticipant the moderator?
  1687. if (roomMemberList[roomsParticipantIndex]->roomMemberMode!=RMM_MODERATOR)
  1688. return REC_UNBAN_MEMBER_MUST_BE_MODERATOR;
  1689. unsigned int banIndex = GetBannedIndex(name);
  1690. if (banIndex==-1)
  1691. return REC_UNBAN_MEMBER_NOT_BANNED;
  1692. banList.RemoveAtIndexFast(banIndex);
  1693. return REC_SUCCESS;
  1694. }
  1695. RoomsErrorCode Room::GetBanReason(RakNet::RakString name, RakNet::RakString *reason)
  1696. {
  1697. RakAssert(roomDestroyed==false);
  1698. unsigned int banIndex = GetBannedIndex(name);
  1699. if (banIndex==-1)
  1700. return REC_GET_BAN_REASON_NOT_BANNED;
  1701. *reason = banList[banIndex].reason;
  1702. return REC_SUCCESS;
  1703. }
  1704. RoomsErrorCode Room::LeaveRoom(RoomsParticipant* roomsParticipant, RemoveUserResult *removeUserResult)
  1705. {
  1706. RakAssert(roomDestroyed==false);
  1707. return RemoveUser(roomsParticipant,removeUserResult);
  1708. }
  1709. /*
  1710. RoomsErrorCode Room::GetKickReason(RoomsParticipant* roomsParticipant, RakNet::RakString *kickReason)
  1711. {
  1712. RakAssert(roomDestroyed==false);
  1713. // Is roomsParticipant in a kick slot?
  1714. unsigned int roomsParticipantIndex = GetKickSlotIndex(roomsParticipant);
  1715. if (roomsParticipantIndex==-1) return REC_GET_KICK_REASON_NOT_KICKED;
  1716. *kickReason=kickedList[roomsParticipantIndex].reason;
  1717. return REC_SUCCESS;
  1718. }
  1719. */
  1720. RoomsErrorCode Room::JoinByFilter(RoomsParticipant* roomsParticipant, RoomMemberMode roomMemberMode, JoinedRoomResult *joinRoomResult)
  1721. {
  1722. RakAssert(roomDestroyed==false);
  1723. if (roomMemberMode==RMM_MODERATOR) return REC_JOIN_BY_FILTER_CANNOT_JOIN_AS_MODERATOR;
  1724. // Is the roomOutput locked for the target slot type (any slot and RLS_ALL_LOCKED, or player and RLS_PLAYERS_LOCKED)?
  1725. joinRoomResult->roomOutput=0;
  1726. bool joinAsSpectator = roomMemberMode==RMM_SPECTATOR_PUBLIC || roomMemberMode==RMM_SPECTATOR_RESERVED || roomMemberMode==RMM_ANY_SPECTATOR;
  1727. ParticipantCanJoinRoomResult pcjrr = ParticipantCanJoinRoom(roomsParticipant, joinAsSpectator, true);
  1728. if (pcjrr==PCJRR_BANNED) return REC_JOIN_BY_FILTER_BANNED;
  1729. if (pcjrr==PCJRR_NO_PUBLIC_SLOTS || pcjrr==PCJRR_NO_PUBLIC_OR_RESERVED_SLOTS) return REC_JOIN_BY_FILTER_NO_SLOTS;
  1730. if (pcjrr==PCJRR_LOCKED) return REC_JOIN_BY_FILTER_ROOM_LOCKED;
  1731. RakAssert(pcjrr==PCJRR_SUCCESS);
  1732. joinRoomResult->roomOutput=this;
  1733. unsigned int firstInviteIndex = GetFirstInviteIndex(roomsParticipant->GetName());
  1734. if (roomMemberMode==RMM_ANY_SPECTATOR)
  1735. {
  1736. if (firstInviteIndex==-1)
  1737. roomMemberMode=RMM_SPECTATOR_PUBLIC;
  1738. else
  1739. roomMemberMode=RMM_SPECTATOR_RESERVED;
  1740. }
  1741. else if (roomMemberMode==RMM_ANY_PLAYABLE)
  1742. {
  1743. if (firstInviteIndex==-1)
  1744. roomMemberMode=RMM_PUBLIC;
  1745. else
  1746. roomMemberMode=RMM_RESERVED;
  1747. }
  1748. RoomMember *rm = new RoomMember;
  1749. rm->roomsParticipant=roomsParticipant;
  1750. rm->roomMemberMode=roomMemberMode;
  1751. roomMemberList.Insert(rm, _FILE_AND_LINE_ );
  1752. roomsParticipant->SetRoom(this);
  1753. if (firstInviteIndex!=-1)
  1754. {
  1755. joinRoomResult->acceptedInvitor=roomMemberList[firstInviteIndex]->roomsParticipant;
  1756. inviteList.RemoveAtIndex(firstInviteIndex);
  1757. }
  1758. else
  1759. joinRoomResult->acceptedInvitor=0;
  1760. // Moderator does not count towards a slot
  1761. UpdateUsedSlots();
  1762. RakAssert(GetNumericProperty(DefaultRoomColumns::TC_USED_SLOTS)==roomMemberList.Size()-1);
  1763. joinRoomResult->joiningMember=roomsParticipant;
  1764. return REC_SUCCESS;
  1765. }
  1766. RoomsErrorCode Room::JoinByQuickJoin(RoomsParticipant* roomsParticipant, RoomMemberMode roomMemberMode, JoinedRoomResult *joinRoomResult)
  1767. {
  1768. RakAssert(roomDestroyed==false);
  1769. // Use same function, just add to the error code if one is returned
  1770. RoomsErrorCode roomsErrorCode = JoinByFilter(roomsParticipant, roomMemberMode, joinRoomResult);
  1771. if (roomsErrorCode!=REC_SUCCESS)
  1772. {
  1773. int val = (int) roomsErrorCode;
  1774. val += (int)REC_JOIN_BY_QUICK_JOIN_CANNOT_JOIN_AS_MODERATOR-(int)REC_JOIN_BY_FILTER_CANNOT_JOIN_AS_MODERATOR;
  1775. roomsErrorCode=(RoomsErrorCode)val;
  1776. }
  1777. else
  1778. {
  1779. // Moderator does not count towards a slot
  1780. UpdateUsedSlots();
  1781. RakAssert(GetNumericProperty(DefaultRoomColumns::TC_USED_SLOTS)==roomMemberList.Size()-1);
  1782. }
  1783. return roomsErrorCode;
  1784. }
  1785. ParticipantCanJoinRoomResult Room::ParticipantCanJoinRoom( RoomsParticipant* roomsParticipant, bool asSpectator, bool checkHasInvite )
  1786. {
  1787. RakAssert(roomDestroyed==false);
  1788. // Is roomsParticipant already in the room?
  1789. unsigned int roomsParticipantIndex = GetRoomIndex(roomsParticipant);
  1790. if (roomsParticipantIndex!=-1)
  1791. return PCJRR_SLOT_ALREADY_USED;
  1792. return ParticipantCanJoinAsPlayer(roomsParticipant, asSpectator, checkHasInvite);
  1793. }
  1794. ParticipantCanJoinRoomResult Room::ParticipantCanJoinAsPlayer( RoomsParticipant* roomsParticipant, bool asSpectator, bool checkHasInvite )
  1795. {
  1796. // Is the room locked?
  1797. if (roomLockState==RLS_PLAYERS_LOCKED && asSpectator==false)
  1798. return PCJRR_LOCKED;
  1799. // Is the room locked?
  1800. if (roomLockState==RLS_ALL_LOCKED)
  1801. return PCJRR_LOCKED;
  1802. // Is the player banned?
  1803. if (GetBannedIndex(roomsParticipant->GetName())!=-1)
  1804. return PCJRR_BANNED;
  1805. // Any slots?
  1806. bool hasInvite = HasInvite(roomsParticipant->GetName());
  1807. bool publicAvailable = HasOpenPublicSlots();
  1808. if (asSpectator==false)
  1809. {
  1810. if (hasInvite==false && checkHasInvite)
  1811. {
  1812. if (publicAvailable==false)
  1813. return PCJRR_NO_PUBLIC_SLOTS;
  1814. }
  1815. // Invited will join public if no reserved slots are open
  1816. bool reservedAvailable = HasOpenReservedSlots();
  1817. if (publicAvailable==false && reservedAvailable==false)
  1818. return PCJRR_NO_PUBLIC_OR_RESERVED_SLOTS;
  1819. }
  1820. else
  1821. {
  1822. if (HasOpenSpectatorSlots()==false)
  1823. return PCJRR_NO_SPECTATOR_SLOTS;
  1824. }
  1825. return PCJRR_SUCCESS;
  1826. }
  1827. bool Room::IsRoomDead(void) const
  1828. {
  1829. return roomMemberList.Size()==0 || roomDestroyed==true;
  1830. }
  1831. RoomsErrorCode Room::GetInvitesToParticipant(RoomsParticipant* roomsParticipant, DataStructures::List<InvitedUser*> &invites)
  1832. {
  1833. RakAssert(roomDestroyed==false);
  1834. unsigned int i;
  1835. for (i=0; i < inviteList.Size(); i++)
  1836. {
  1837. if (inviteList[i].target==roomsParticipant->GetName())
  1838. invites.Insert(&inviteList[i], _FILE_AND_LINE_ );
  1839. }
  1840. return REC_SUCCESS;
  1841. }
  1842. RoomsParticipant* Room::GetModerator(void) const
  1843. {
  1844. unsigned int i;
  1845. for (i=0; i < roomMemberList.Size(); i++)
  1846. if (roomMemberList[i]->roomMemberMode==RMM_MODERATOR)
  1847. return roomMemberList[i]->roomsParticipant;
  1848. RakAssert("Room::GetModerator: Room should always have a moderator" && 0);
  1849. return 0;
  1850. }
  1851. RoomID Room::GetID(void) const
  1852. {
  1853. return lobbyRoomId;
  1854. }
  1855. double Room::GetNumericProperty(int index) const
  1856. {
  1857. return tableRow->cells[index]->i;
  1858. }
  1859. const char *Room::GetStringProperty(int index) const
  1860. {
  1861. return tableRow->cells[index]->c;
  1862. }
  1863. void Room::SetNumericProperty(int index, double value)
  1864. {
  1865. tableRow->cells[index]->Set(value);
  1866. }
  1867. void Room::SetStringProperty(int index, const char *value)
  1868. {
  1869. tableRow->cells[index]->Set(value);
  1870. }
  1871. RoomsErrorCode Room::RemoveUser(RoomsParticipant* roomsParticipant,RemoveUserResult *removeUserResult)
  1872. {
  1873. RakAssert(roomDestroyed==false);
  1874. removeUserResult->gotNewModerator=false;
  1875. removeUserResult->removedFromRoom=false;
  1876. removeUserResult->room=this;
  1877. unsigned int roomsParticipantIndex = GetRoomIndex(roomsParticipant);
  1878. if (roomsParticipantIndex==-1) return REC_REMOVE_USER_NOT_IN_ROOM;
  1879. removeUserResult->removedFromRoom=true;
  1880. removeUserResult->removedUserAddress=roomsParticipant->GetSystemAddress();
  1881. removeUserResult->removedUserName=roomsParticipant->GetName();
  1882. if (roomMemberList[roomsParticipantIndex]->roomMemberMode==RMM_MODERATOR)
  1883. {
  1884. int destroyOnModeratorLeave;
  1885. tableRow->cells[DefaultRoomColumns::TC_DESTROY_ON_MODERATOR_LEAVE]->Get(&destroyOnModeratorLeave);
  1886. if (destroyOnModeratorLeave || roomMemberList.Size()==1)
  1887. {
  1888. removeUserResult->clearedInvitations=inviteList;
  1889. inviteList.Clear(false, _FILE_AND_LINE_);
  1890. removeUserResult->roomDestroyed=true;
  1891. unsigned int i;
  1892. for (i=0; i < roomMemberList.Size(); i++)
  1893. roomMemberList[i]->roomsParticipant->SetRoom(0);
  1894. roomDestroyed=true;
  1895. removeUserResult->roomDestroyed=true;
  1896. // Up to caller to call PerGamesRoomContainer::DestroyRoom();
  1897. return REC_SUCCESS;
  1898. }
  1899. // Transfer moderator to the next player, if any. Reserved slot players take priority to be moderator.
  1900. unsigned int nextModIndex;
  1901. for (nextModIndex = 0; nextModIndex < roomMemberList.Size(); nextModIndex++)
  1902. {
  1903. if (roomMemberList[nextModIndex]->roomMemberMode==RMM_RESERVED)
  1904. {
  1905. roomMemberList[nextModIndex]->roomMemberMode=RMM_MODERATOR;
  1906. removeUserResult->gotNewModerator=true;
  1907. break;
  1908. }
  1909. }
  1910. if (removeUserResult->gotNewModerator==false)
  1911. {
  1912. for (nextModIndex = 0; nextModIndex < roomMemberList.Size(); nextModIndex++)
  1913. {
  1914. if (roomMemberList[nextModIndex]->roomMemberMode==RMM_PUBLIC)
  1915. {
  1916. roomMemberList[nextModIndex]->roomMemberMode=RMM_MODERATOR;
  1917. removeUserResult->gotNewModerator=true;
  1918. break;
  1919. }
  1920. }
  1921. }
  1922. // If moderator and clearInvitesOnNewModerator, clear invitations and add to removeUserResult->clearedInvitations
  1923. if (clearInvitesOnNewModerator)
  1924. {
  1925. removeUserResult->clearedInvitations=inviteList;
  1926. inviteList.Clear(false, _FILE_AND_LINE_);
  1927. unsigned int i;
  1928. for (i=0; i < roomMemberList.Size(); i++)
  1929. {
  1930. if (roomMemberList[i]->roomMemberMode==RMM_SPECTATOR_RESERVED)
  1931. roomMemberList[i]->roomMemberMode=RMM_SPECTATOR_PUBLIC;
  1932. }
  1933. }
  1934. }
  1935. delete roomMemberList[roomsParticipantIndex];
  1936. roomMemberList.RemoveAtIndex(roomsParticipantIndex);
  1937. roomsParticipant->SetRoom(0);
  1938. removeUserResult->roomDestroyed=IsRoomDead();
  1939. roomDestroyed=removeUserResult->roomDestroyed;
  1940. removeUserResult->removedFromRoom=true;
  1941. if (removeUserResult->roomDestroyed==false)
  1942. UpdateUsedSlots();
  1943. return REC_SUCCESS;
  1944. }
  1945. bool Room::IsRoomLockedToSpectators(void) const
  1946. {
  1947. return roomLockState==RLS_ALL_LOCKED;
  1948. }
  1949. bool Room::IsRoomLockedToPlayers(void) const
  1950. {
  1951. return roomLockState==RLS_PLAYERS_LOCKED || roomLockState==RLS_ALL_LOCKED;
  1952. }
  1953. bool Room::IsInRoom(RoomsParticipant* roomsParticipant) const
  1954. {
  1955. return GetRoomIndex(roomsParticipant)!=-1;
  1956. }
  1957. bool Room::HasInvite(RakNet::RakString roomsParticipant)
  1958. {
  1959. return GetFirstInviteIndex(roomsParticipant)!=-1;
  1960. }
  1961. unsigned int Room::GetRoomIndex(RoomsParticipant* roomsParticipant) const
  1962. {
  1963. unsigned int i;
  1964. for (i=0; i < roomMemberList.Size(); i++)
  1965. if (roomMemberList[i]->roomsParticipant==roomsParticipant)
  1966. return i;
  1967. return (unsigned int) -1;
  1968. }
  1969. /*
  1970. unsigned int Room::GetKickSlotIndex(RoomsParticipant* roomsParticipant) const
  1971. {
  1972. unsigned int i;
  1973. for (i=0; i < kickedList.Size(); i++)
  1974. if (kickedList[i].roomsParticipant==roomsParticipant)
  1975. return i;
  1976. return -1;
  1977. }
  1978. */
  1979. unsigned int Room::GetBannedIndex(RakNet::RakString username) const
  1980. {
  1981. unsigned int i;
  1982. for (i=0; i < banList.Size(); i++)
  1983. if (banList[i].target==username)
  1984. return i;
  1985. return (unsigned int) -1;
  1986. }
  1987. unsigned int Room::GetInviteIndex(RakNet::RakString invitee, RakNet::RakString invitor) const
  1988. {
  1989. unsigned int i;
  1990. for (i=0; i < inviteList.Size(); i++)
  1991. if (inviteList[i].target==invitee && inviteList[i].invitorName==invitor)
  1992. return i;
  1993. return (unsigned int) -1;
  1994. }
  1995. unsigned int Room::GetFirstInviteIndex(RakNet::RakString invitee) const
  1996. {
  1997. unsigned int i;
  1998. for (i=0; i < inviteList.Size(); i++)
  1999. if (inviteList[i].target==invitee)
  2000. return i;
  2001. return (unsigned int) -1;
  2002. }
  2003. bool Room::AreAllPlayableSlotsFilled(void) const
  2004. {
  2005. return HasOpenPublicSlots()==false && HasOpenReservedSlots()==false;
  2006. }
  2007. bool Room::HasOpenPublicSlots(void) const
  2008. {
  2009. return GetNumericProperty(DefaultRoomColumns::TC_REMAINING_PUBLIC_SLOTS)!=0.0;
  2010. }
  2011. bool Room::HasOpenReservedSlots(void) const
  2012. {
  2013. return GetNumericProperty(DefaultRoomColumns::TC_REMAINING_RESERVED_SLOTS)!=0.0;
  2014. }
  2015. bool Room::HasOpenSpectatorSlots(void) const
  2016. {
  2017. return GetNumericProperty(DefaultRoomColumns::TC_REMAINING_SPECTATOR_SLOTS)!=0.0;
  2018. }
  2019. bool Room::IsHiddenToParticipant(RoomsParticipant* roomsParticipant) const
  2020. {
  2021. if (hiddenFromSearches==false)
  2022. return false;
  2023. if (IsInRoom(roomsParticipant))
  2024. return false;
  2025. if (GetFirstInviteIndex(roomsParticipant->GetName())!=-1)
  2026. return false;
  2027. return true;
  2028. }
  2029. void Room::ChangeHandle(RakNet::RakString oldHandle, RakNet::RakString newHandle)
  2030. {
  2031. if (oldHandle==newHandle)
  2032. return;
  2033. unsigned int index;
  2034. index = GetBannedIndex(newHandle);
  2035. RakAssert(index==-1);
  2036. index = GetFirstInviteIndex(newHandle);
  2037. RakAssert(index==-1);
  2038. index = GetBannedIndex(oldHandle);
  2039. if (index!=-1)
  2040. banList[index].target=newHandle;
  2041. for (index=0; index < inviteList.Size(); index++)
  2042. {
  2043. if (inviteList[index].target==oldHandle)
  2044. inviteList[index].target=newHandle;
  2045. if (inviteList[index].invitorName==oldHandle)
  2046. inviteList[index].invitorName=newHandle;
  2047. }
  2048. }
  2049. // ---------------------------- UNIT TEST ----------------------------
  2050. void AllGamesRoomsContainer::UnitTest(void)
  2051. {
  2052. RoomsErrorCodeDescription::Validate();
  2053. AllGamesRoomsContainer agrc;
  2054. RoomsErrorCode roomsErrorCode;
  2055. GameIdentifier gameIdentifier1, gameIdentifier2;
  2056. DataStructures::List<InvitedUser> clearedInvitations;
  2057. gameIdentifier1="gameIdentifier1";
  2058. gameIdentifier2="gameIdentifier2";
  2059. RoomsParticipant roomsParticipant1, roomsParticipant2;
  2060. roomsParticipant1.SetName("roomsParticipant1");
  2061. roomsParticipant2.SetName("roomsParticipant2");
  2062. RoomQuery roomQuery;
  2063. roomQuery.numQueries=2;
  2064. DataStructures::Table::FilterQuery filterQuery[2];
  2065. roomQuery.queries=filterQuery;
  2066. DataStructures::Table::Cell cells[2];
  2067. filterQuery[0].cellValue=&cells[0];
  2068. filterQuery[1].cellValue=&cells[1];
  2069. strcpy(filterQuery[0].columnName, "LevelName");
  2070. strcpy(filterQuery[1].columnName, "FlagCaptureCount");
  2071. filterQuery[0].operation=DataStructures::Table::QF_EQUAL;
  2072. filterQuery[1].operation=DataStructures::Table::QF_NOT_EQUAL;
  2073. cells[0].Set("DogFoodLevel");
  2074. cells[1].Set(10);
  2075. DataStructures::OrderedList<Room*, Room*, RoomsSortByName> roomsOutput;
  2076. bool onlyJoinable;
  2077. RemoveUserResult removeUserResult;
  2078. QuickJoinUser quickJoinUser;
  2079. DataStructures::List<QuickJoinUser*> timeoutExpired;
  2080. DataStructures::List<JoinedRoomResult> joinedRoomMembers;
  2081. Room *room;
  2082. RoomCreationParameters roomCreationParameters;
  2083. quickJoinUser.networkedQuickJoinUser.minimumPlayers=2;
  2084. quickJoinUser.networkedQuickJoinUser.query=roomQuery;
  2085. quickJoinUser.roomsParticipant=&roomsParticipant1;
  2086. quickJoinUser.networkedQuickJoinUser.timeout=5000;
  2087. ProfanityFilter profanityFilter;
  2088. profanityFilter.AddWord("BADWORD");
  2089. DataStructures::Table customRoomProperties;
  2090. customRoomProperties.AddColumn(filterQuery[0].columnName, DataStructures::Table::STRING);
  2091. customRoomProperties.AddColumn(filterQuery[1].columnName, DataStructures::Table::NUMERIC);
  2092. DataStructures::List<QuickJoinUser*> dereferencedPointers;
  2093. DataStructures::List<DataStructures::Table::Cell*> cellList;
  2094. DataStructures::List<InvitedUser*> invites;
  2095. RakNet::RakString kickReason;
  2096. cellList.Insert(&cells[0], _FILE_AND_LINE_ );
  2097. cellList.Insert(&cells[1], _FILE_AND_LINE_ );
  2098. customRoomProperties.AddRow(0, cellList);
  2099. // Search by filter
  2100. onlyJoinable=true;
  2101. roomsErrorCode = agrc.SearchByFilter( gameIdentifier1, &roomsParticipant1, &roomQuery, roomsOutput, onlyJoinable );
  2102. RakAssert(roomsErrorCode==REC_SEARCH_BY_FILTER_UNKNOWN_TITLE);
  2103. // leave room
  2104. roomsErrorCode = agrc.LeaveRoom(&roomsParticipant1, &removeUserResult);
  2105. RakAssert(roomsErrorCode==REC_LEAVE_ROOM_NOT_IN_ROOM);
  2106. // Add title
  2107. roomsErrorCode = agrc.AddTitle(gameIdentifier1);
  2108. RakAssert(roomsErrorCode==REC_SUCCESS);
  2109. roomsErrorCode = agrc.AddTitle(gameIdentifier1);
  2110. RakAssert(roomsErrorCode==REC_ADD_TITLE_ALREADY_IN_USE);
  2111. // Search by filter
  2112. roomsErrorCode = agrc.SearchByFilter( gameIdentifier1, &roomsParticipant1, &roomQuery, roomsOutput, onlyJoinable );
  2113. RakAssert(roomsErrorCode==REC_SUCCESS);
  2114. // Search by filter (another game)
  2115. roomsErrorCode = agrc.SearchByFilter( gameIdentifier2, &roomsParticipant1, &roomQuery, roomsOutput, onlyJoinable );
  2116. RakAssert(roomsErrorCode==REC_SEARCH_BY_FILTER_UNKNOWN_TITLE);
  2117. // leave room
  2118. roomsErrorCode = agrc.LeaveRoom( &roomsParticipant1, &removeUserResult);
  2119. RakAssert(roomsErrorCode==REC_LEAVE_ROOM_NOT_IN_ROOM);
  2120. // Quick join
  2121. roomsErrorCode = agrc.AddUserToQuickJoin(gameIdentifier1, &quickJoinUser);
  2122. RakAssert(roomsErrorCode==REC_SUCCESS);
  2123. // Process quick join
  2124. roomsErrorCode = agrc.ProcessQuickJoins( timeoutExpired, joinedRoomMembers, dereferencedPointers, 1000);
  2125. RakAssert(roomsErrorCode==REC_SUCCESS);
  2126. // Let timeout expire
  2127. // Process quick join
  2128. roomsErrorCode = agrc.ProcessQuickJoins( timeoutExpired, joinedRoomMembers, dereferencedPointers, 5000);
  2129. RakAssert(roomsErrorCode==REC_SUCCESS);
  2130. RakAssert(timeoutExpired.Size()==1 && timeoutExpired[0]==&quickJoinUser);
  2131. // Quick join
  2132. roomsErrorCode = agrc.AddUserToQuickJoin(gameIdentifier1, &quickJoinUser);
  2133. RakAssert(roomsErrorCode==REC_SUCCESS);
  2134. // Quick join (should fail)
  2135. roomsErrorCode = agrc.AddUserToQuickJoin(gameIdentifier1, &quickJoinUser);
  2136. RakAssert(roomsErrorCode==REC_ADD_TO_QUICK_JOIN_ALREADY_THERE);
  2137. // Create room (should fail due to in quick join)
  2138. roomCreationParameters.networkedRoomCreationParameters.inviteToRoomPermission=NetworkedRoomCreationParameters::INVITE_MODE_RESERVED_SLOTS_CAN_INVITE;
  2139. roomCreationParameters.networkedRoomCreationParameters.inviteToSpectatorSlotPermission=NetworkedRoomCreationParameters::INVITE_MODE_RESERVED_SLOTS_CAN_INVITE;
  2140. roomCreationParameters.networkedRoomCreationParameters.autoLockReadyStatus=true;
  2141. roomCreationParameters.networkedRoomCreationParameters.clearInvitesOnNewModerator=true;
  2142. roomCreationParameters.networkedRoomCreationParameters.roomName="BADWORD room";
  2143. roomCreationParameters.firstUser=&roomsParticipant1;
  2144. roomCreationParameters.gameIdentifier=gameIdentifier1;
  2145. roomCreationParameters.networkedRoomCreationParameters.slots.publicSlots=1;
  2146. roomCreationParameters.networkedRoomCreationParameters.slots.reservedSlots=1;
  2147. roomCreationParameters.networkedRoomCreationParameters.slots.spectatorSlots=1;
  2148. roomsErrorCode = agrc.CreateRoom(&roomCreationParameters, &profanityFilter);
  2149. RakAssert(roomsErrorCode==REC_CREATE_ROOM_CURRENTLY_IN_QUICK_JOIN);
  2150. // Cancel quick join
  2151. QuickJoinUser *qju;
  2152. roomsErrorCode = agrc.RemoveUserFromQuickJoin(quickJoinUser.roomsParticipant, &qju);
  2153. RakAssert(roomsErrorCode==REC_SUCCESS);
  2154. // Create room (should fail due to bad word)
  2155. roomsErrorCode = agrc.CreateRoom(&roomCreationParameters, &profanityFilter);
  2156. RakAssert(roomsErrorCode==REC_ROOM_CREATION_PARAMETERS_ROOM_NAME_HAS_PROFANITY);
  2157. // Create room
  2158. roomCreationParameters.networkedRoomCreationParameters.roomName="My room";
  2159. roomsErrorCode = agrc.CreateRoom(&roomCreationParameters, &profanityFilter);
  2160. RakAssert(roomsErrorCode==REC_SUCCESS);
  2161. RakAssert(roomCreationParameters.roomOutput);
  2162. // Create room (should fail due to already in room)
  2163. roomsErrorCode = agrc.CreateRoom(&roomCreationParameters, &profanityFilter);
  2164. RakAssert(roomsErrorCode==REC_CREATE_ROOM_CURRENTLY_IN_A_ROOM);
  2165. // Quick join (should fail due to already in room)
  2166. roomsErrorCode = agrc.AddUserToQuickJoin(gameIdentifier1, &quickJoinUser);
  2167. RakAssert(roomsErrorCode==REC_ADD_TO_QUICK_JOIN_CURRENTLY_IN_A_ROOM);
  2168. // Search by filter
  2169. roomsErrorCode = agrc.SearchByFilter( gameIdentifier1, &roomsParticipant1, &roomQuery, roomsOutput, onlyJoinable );
  2170. RakAssert(roomsErrorCode==REC_SUCCESS);
  2171. RakAssert(roomsOutput.Size()==0);
  2172. // Set room properties (Should fail due to not being in the room)
  2173. roomsErrorCode = agrc.SetCustomRoomProperties( &roomsParticipant2, &customRoomProperties );
  2174. RakAssert(roomsErrorCode==REC_SET_CUSTOM_ROOM_PROPERTIES_UNKNOWN_ROOM_ID);
  2175. // Set room properties
  2176. roomsErrorCode = agrc.SetCustomRoomProperties( &roomsParticipant1, &customRoomProperties );
  2177. RakAssert(roomsErrorCode==REC_SUCCESS);
  2178. // Search by filter, including not joinable
  2179. RakAssert(&filterQuery[1]==&roomQuery.queries[1]);
  2180. roomQuery.queries[1].cellValue->Set(1234); // Query 1 is not equal, change to something else
  2181. roomsErrorCode = agrc.SearchByFilter( gameIdentifier1, &roomsParticipant1, &roomQuery, roomsOutput, false );
  2182. RakAssert(roomsErrorCode==REC_SUCCESS);
  2183. RakAssert(roomsOutput.Size()==1);
  2184. // Invite member to room (yourself, should fail)
  2185. roomsErrorCode = agrc.SendInvite( &roomsParticipant1, &roomsParticipant1, false, "SendInviteSubject", "SendInviteBody" );
  2186. RakAssert(roomsErrorCode==REC_SEND_INVITE_CANNOT_PERFORM_ON_SELF);
  2187. // Invite member to room
  2188. roomsErrorCode = agrc.SendInvite( &roomsParticipant1, &roomsParticipant2, false, "SendInviteSubject", "SendInviteBody" );
  2189. RakAssert(roomsErrorCode==REC_SUCCESS);
  2190. // Get invites to member
  2191. roomsErrorCode = agrc.GetInvitesToParticipant(&roomsParticipant2, invites);
  2192. RakAssert(roomsErrorCode==REC_SUCCESS);
  2193. RakAssert(invites.Size()==1);
  2194. RakAssert(invites[0]->subject=="SendInviteSubject");
  2195. RakAssert(invites[0]->invitorName==roomsParticipant1.GetName());
  2196. // Leave room
  2197. roomsErrorCode = agrc.LeaveRoom( &roomsParticipant1, &removeUserResult);
  2198. RakAssert(roomsParticipant1.GetRoom()==0);
  2199. RakAssert(roomsErrorCode==REC_SUCCESS);
  2200. RakAssert(removeUserResult.removedFromQuickJoin==false);
  2201. RakAssert(removeUserResult.removedFromRoom==true);
  2202. RakAssert(removeUserResult.room==roomCreationParameters.roomOutput);
  2203. RakAssert(removeUserResult.clearedInvitations.Size()==1);
  2204. RakAssert(removeUserResult.roomDestroyed==true);
  2205. // Clear room pointer
  2206. agrc.DestroyRoomIfDead(removeUserResult.room);
  2207. // Create room
  2208. // Clear invites on moderator changes or leaves
  2209. roomCreationParameters.networkedRoomCreationParameters.destroyOnModeratorLeave=false;
  2210. roomCreationParameters.networkedRoomCreationParameters.clearInvitesOnNewModerator=true;
  2211. roomsErrorCode = agrc.CreateRoom(&roomCreationParameters, &profanityFilter);
  2212. RakAssert(roomsErrorCode==REC_SUCCESS);
  2213. RakAssert(roomCreationParameters.roomOutput);
  2214. RakAssert(roomCreationParameters.roomOutput->GetNumericProperty(DefaultRoomColumns::TC_USED_PUBLIC_PLUS_RESERVED_SLOTS)==0);
  2215. // Invite member to room
  2216. roomsErrorCode = agrc.SendInvite( &roomsParticipant1, &roomsParticipant2, false, "SendInviteSubject", "SendInviteBody" );
  2217. RakAssert(roomsErrorCode==REC_SUCCESS);
  2218. RakAssert(roomCreationParameters.roomOutput->GetNumericProperty(DefaultRoomColumns::TC_USED_PUBLIC_PLUS_RESERVED_SLOTS)==0);
  2219. // member accepts invite (backwards parameters)
  2220. roomsErrorCode = agrc.AcceptInvite( roomsParticipant1.GetRoom()->GetID(), &room, &roomsParticipant1, roomsParticipant2.GetName() );
  2221. RakAssert(roomsErrorCode==REC_ACCEPT_INVITE_CURRENTLY_IN_A_ROOM);
  2222. RakAssert(roomCreationParameters.roomOutput->GetNumericProperty(DefaultRoomColumns::TC_USED_PUBLIC_PLUS_RESERVED_SLOTS)==0);
  2223. // member accepts invite (correct parameters)
  2224. roomsErrorCode = agrc.AcceptInvite( roomsParticipant1.GetRoom()->GetID(), &room, &roomsParticipant2, roomsParticipant1.GetName() );
  2225. RakAssert(roomsErrorCode==REC_SUCCESS);
  2226. RakAssert(roomsParticipant2.GetRoom()!=0);
  2227. RakAssert(roomsParticipant1.GetRoom()==roomsParticipant2.GetRoom());
  2228. RakAssert(roomCreationParameters.roomOutput->GetNumericProperty(DefaultRoomColumns::TC_USED_PUBLIC_PLUS_RESERVED_SLOTS)==1);
  2229. // change moderator
  2230. roomsErrorCode = agrc.GrantModerator( &roomsParticipant1, &roomsParticipant2, clearedInvitations );
  2231. RakAssert(roomsErrorCode==REC_SUCCESS);
  2232. RakAssert(roomCreationParameters.roomOutput->GetNumericProperty(DefaultRoomColumns::TC_USED_PUBLIC_PLUS_RESERVED_SLOTS)==1);
  2233. // new member invites existing member
  2234. roomsErrorCode = agrc.SendInvite( &roomsParticipant2, &roomsParticipant1, false, "SendInviteSubject", "SendInviteBody" );
  2235. RakAssert(roomsErrorCode==REC_SEND_INVITE_INVITEE_ALREADY_IN_THIS_ROOM);
  2236. RakAssert(roomCreationParameters.roomOutput->GetNumericProperty(DefaultRoomColumns::TC_USED_PUBLIC_PLUS_RESERVED_SLOTS)==1);
  2237. // Moderator leaves
  2238. roomsErrorCode = agrc.LeaveRoom( &roomsParticipant2, &removeUserResult );
  2239. RakAssert(roomsErrorCode==REC_SUCCESS);
  2240. RakAssert(removeUserResult.gotNewModerator==true);
  2241. RakAssert(roomCreationParameters.roomOutput->GetModerator()==&roomsParticipant1);
  2242. RakAssert(roomsParticipant2.GetRoom()==0);
  2243. RakAssert(roomCreationParameters.roomOutput->GetNumericProperty(DefaultRoomColumns::TC_USED_PUBLIC_PLUS_RESERVED_SLOTS)==0);
  2244. // Invite the guy that just left
  2245. roomsErrorCode = agrc.SendInvite( &roomsParticipant1, &roomsParticipant2, false, "SendInviteSubject", "SendInviteBody" );
  2246. RakAssert(roomsErrorCode==REC_SUCCESS);
  2247. // member accepts invite
  2248. roomsErrorCode = agrc.AcceptInvite( roomsParticipant1.GetRoom()->GetID(), &room, &roomsParticipant2, roomsParticipant1.GetName() );
  2249. RakAssert(roomsErrorCode==REC_SUCCESS);
  2250. RakAssert(roomCreationParameters.roomOutput->GetNumericProperty(DefaultRoomColumns::TC_USED_PUBLIC_PLUS_RESERVED_SLOTS)==1);
  2251. // change current moderator to to spectator (should fail)
  2252. roomsErrorCode = agrc.StartSpectating( &roomsParticipant1 );
  2253. RakAssert(roomsErrorCode==REC_START_SPECTATING_REASSIGN_MODERATOR_BEFORE_SPECTATE);
  2254. // change other member to spectator
  2255. roomsErrorCode = agrc.StartSpectating( &roomsParticipant2 );
  2256. RakAssert(roomsErrorCode==REC_SUCCESS);
  2257. RakAssert(roomCreationParameters.roomOutput->GetNumericProperty(DefaultRoomColumns::TC_USED_PUBLIC_PLUS_RESERVED_SLOTS)==0);
  2258. // change member type to player
  2259. roomsErrorCode = agrc.StopSpectating( &roomsParticipant2 );
  2260. RakAssert(roomsErrorCode==REC_SUCCESS);
  2261. RakAssert(roomCreationParameters.roomOutput->GetNumericProperty(DefaultRoomColumns::TC_USED_PUBLIC_PLUS_RESERVED_SLOTS)==1);
  2262. // Moderator logs off
  2263. roomsErrorCode = agrc.RemoveUser( &roomsParticipant1, &removeUserResult );
  2264. RakAssert(roomsErrorCode==REC_SUCCESS);
  2265. RakAssert(roomCreationParameters.roomOutput->GetNumericProperty(DefaultRoomColumns::TC_USED_PUBLIC_PLUS_RESERVED_SLOTS)==0);
  2266. RakAssert(roomCreationParameters.roomOutput->GetModerator()==&roomsParticipant2);
  2267. RakAssert(roomsParticipant1.GetRoom()==0);
  2268. // Other player logs off
  2269. roomsErrorCode = agrc.RemoveUser( roomCreationParameters.roomOutput->GetModerator(), &removeUserResult );
  2270. RakAssert(roomsErrorCode==REC_SUCCESS);
  2271. RakAssert(roomsParticipant2.GetRoom()==0);
  2272. agrc.DestroyRoomIfDead(removeUserResult.room);
  2273. // both members quick join with a custom filter (equality).
  2274. QuickJoinUser quickJoinUser1;
  2275. quickJoinUser1.networkedQuickJoinUser.minimumPlayers=2;
  2276. quickJoinUser1.networkedQuickJoinUser.query=roomQuery;
  2277. quickJoinUser1.roomsParticipant=&roomsParticipant1;
  2278. quickJoinUser1.networkedQuickJoinUser.timeout=10000;
  2279. roomsErrorCode = agrc.AddUserToQuickJoin(gameIdentifier1, &quickJoinUser1);
  2280. RakAssert(roomsErrorCode==REC_SUCCESS);
  2281. RakAssert(roomsParticipant1.GetRoom()==0);
  2282. RakAssert(roomsParticipant2.GetRoom()==0);
  2283. RakAssert(roomsParticipant1.GetInQuickJoin()==true);
  2284. QuickJoinUser quickJoinUser2;
  2285. quickJoinUser2.networkedQuickJoinUser.minimumPlayers=2;
  2286. quickJoinUser2.networkedQuickJoinUser.query=roomQuery;
  2287. quickJoinUser2.roomsParticipant=&roomsParticipant2;
  2288. quickJoinUser2.networkedQuickJoinUser.timeout=10000;
  2289. roomsErrorCode = agrc.AddUserToQuickJoin(gameIdentifier1, &quickJoinUser2);
  2290. RakAssert(roomsErrorCode==REC_SUCCESS);
  2291. RakAssert(roomsParticipant1.GetRoom()==0);
  2292. RakAssert(roomsParticipant2.GetRoom()==0);
  2293. RakAssert(roomsParticipant2.GetInQuickJoin()==true);
  2294. // Update quick join. Should create a room
  2295. roomsErrorCode = agrc.ProcessQuickJoins( timeoutExpired, joinedRoomMembers, dereferencedPointers, 1000);
  2296. RakAssert(roomsErrorCode==REC_SUCCESS);
  2297. RakAssert(roomsParticipant1.GetRoom()!=0);
  2298. RakAssert(roomsParticipant1.GetRoom()==roomsParticipant2.GetRoom());
  2299. RakAssert(joinedRoomMembers.Size()==2);
  2300. // Both members log off
  2301. roomsErrorCode = agrc.RemoveUser( &roomsParticipant1, &removeUserResult );
  2302. RakAssert(roomsErrorCode==REC_SUCCESS);
  2303. RakAssert(removeUserResult.room->GetNumericProperty(DefaultRoomColumns::TC_USED_PUBLIC_PLUS_RESERVED_SLOTS)==0);
  2304. RakAssert(removeUserResult.room->GetModerator()==&roomsParticipant2);
  2305. RakAssert(roomsParticipant1.GetRoom()==0);
  2306. roomsErrorCode = agrc.RemoveUser( &roomsParticipant2, &removeUserResult );
  2307. RakAssert(roomsErrorCode==REC_SUCCESS);
  2308. RakAssert(roomsParticipant2.GetRoom()==0);
  2309. agrc.DestroyRoomIfDead(removeUserResult.room);
  2310. // Enter roomOutput (member one) (should create a room)
  2311. JoinedRoomResult joinedRoomResult;
  2312. roomCreationParameters.networkedRoomCreationParameters.slots.publicSlots=0;
  2313. roomsErrorCode = agrc.EnterRoom( &roomCreationParameters, RMM_ANY_PLAYABLE, 0, 0, &joinedRoomResult );
  2314. RakAssert(roomsErrorCode==REC_SUCCESS);
  2315. RakAssert(roomsParticipant1.GetRoom()!=0);
  2316. RakAssert(roomsParticipant1.GetRoom()->GetModerator()==&roomsParticipant1);
  2317. RakAssert(roomCreationParameters.roomOutput->GetNumericProperty(DefaultRoomColumns::TC_REMAINING_PUBLIC_PLUS_RESERVED_SLOTS)==1);
  2318. // Set the properties on the new room
  2319. roomsErrorCode = agrc.SetCustomRoomProperties( &roomsParticipant1, &customRoomProperties );
  2320. RakAssert(roomsErrorCode==REC_SUCCESS);
  2321. RakAssert(agrc.GetPropertyIndex( roomsParticipant1.GetRoom()->GetID(), "LevelName")!=-1);
  2322. RakAssert(roomsParticipant1.GetRoom()->GetStringProperty(agrc.GetPropertyIndex( roomsParticipant1.GetRoom()->GetID(), "LevelName"))!=0);
  2323. // Invite member two to the new room
  2324. roomsErrorCode = agrc.SendInvite( &roomsParticipant1, &roomsParticipant2, false, "SendInviteSubject", "SendInviteBody" );
  2325. RakAssert(roomsErrorCode==REC_SUCCESS);
  2326. // Quick join (member two) (should join the created roomOutput)
  2327. roomsErrorCode = agrc.AddUserToQuickJoin(gameIdentifier1, &quickJoinUser2);
  2328. RakAssert(roomsErrorCode==REC_SUCCESS);
  2329. RakAssert(roomsParticipant2.GetRoom()==0);
  2330. RakAssert(roomsParticipant2.GetInQuickJoin()==true);
  2331. // Update quick join. Should join the room, passing the required filter properties
  2332. roomsErrorCode = agrc.ProcessQuickJoins( timeoutExpired, joinedRoomMembers, dereferencedPointers, 1000);
  2333. RakAssert(roomsErrorCode==REC_SUCCESS);
  2334. RakAssert(roomsParticipant1.GetRoom()!=0);
  2335. RakAssert(roomsParticipant1.GetRoom()==roomsParticipant2.GetRoom());
  2336. RakAssert(joinedRoomMembers.Size()==1);
  2337. RakAssert(cells[0].c);
  2338. RakAssert(strcmp(roomsParticipant1.GetRoom()->GetStringProperty(agrc.GetPropertyIndex( roomsParticipant1.GetRoom()->GetID(), "LevelName")),cells[0].c)==0);
  2339. // Leave roomOutput (member two)
  2340. roomsErrorCode = agrc.LeaveRoom( &roomsParticipant2, &removeUserResult );
  2341. RakAssert(roomsErrorCode==REC_SUCCESS);
  2342. RakAssert(removeUserResult.gotNewModerator==false);
  2343. RakAssert(roomCreationParameters.roomOutput->GetModerator()==&roomsParticipant1);
  2344. RakAssert(roomsParticipant2.GetRoom()==0);
  2345. RakAssert(roomCreationParameters.roomOutput->GetNumericProperty(DefaultRoomColumns::TC_USED_PUBLIC_PLUS_RESERVED_SLOTS)==0);
  2346. // Lock Room
  2347. roomsErrorCode = agrc.SetRoomLockState( &roomsParticipant1, RLS_PLAYERS_LOCKED );
  2348. RakAssert(roomsErrorCode==REC_SUCCESS);
  2349. // Set member ready
  2350. roomsErrorCode = agrc.SetReadyStatus( &roomsParticipant1, true );
  2351. RakAssert(roomsErrorCode==REC_SUCCESS);
  2352. // Set member unready
  2353. roomsErrorCode = agrc.SetReadyStatus( &roomsParticipant1, false );
  2354. RakAssert(roomsErrorCode==REC_SET_READY_STATUS_AUTO_LOCK_ALL_PLAYERS_READY);
  2355. // Unlock room
  2356. roomsErrorCode = agrc.SetRoomLockState( &roomsParticipant1, RLS_NOT_LOCKED );
  2357. RakAssert(roomsErrorCode==REC_SUCCESS);
  2358. // Set member unready
  2359. room=roomCreationParameters.roomOutput;
  2360. roomsErrorCode = agrc.SetReadyStatus( &roomsParticipant1, false );
  2361. RakAssert(roomsErrorCode==REC_SUCCESS);
  2362. // Try to enter the room (no public slots, tried to create room of same name, failed)
  2363. roomCreationParameters.firstUser=&roomsParticipant2;
  2364. roomsErrorCode = agrc.EnterRoom( &roomCreationParameters, RMM_ANY_PLAYABLE, 0, 0, &joinedRoomResult );
  2365. RakAssert(roomsErrorCode==REC_ROOM_CREATION_PARAMETERS_ROOM_NAME_IN_USE);
  2366. // Open a public slot
  2367. Slots slots;
  2368. slots.publicSlots=1;
  2369. roomsErrorCode = agrc.ChangeSlotCounts( &roomsParticipant1, slots );
  2370. RakAssert(roomsErrorCode==REC_SUCCESS);
  2371. // Enter room
  2372. roomCreationParameters.firstUser=&roomsParticipant2;
  2373. roomsErrorCode = agrc.EnterRoom( &roomCreationParameters, RMM_ANY_PLAYABLE, 0, 0, &joinedRoomResult );
  2374. RakAssert(roomsErrorCode==REC_SUCCESS);
  2375. RakAssert(roomsParticipant1.GetRoom()!=0);
  2376. RakAssert(roomsParticipant1.GetRoom()->GetModerator()==&roomsParticipant1);
  2377. RakAssert(roomsParticipant1.GetRoom()==roomsParticipant2.GetRoom());
  2378. RakAssert(joinedRoomResult.roomOutput->GetNumericProperty(DefaultRoomColumns::TC_REMAINING_PUBLIC_PLUS_RESERVED_SLOTS)==1);
  2379. room = joinedRoomResult.roomOutput;
  2380. // Kick member 2
  2381. RakNet::RakString banReason("Don't like you");
  2382. roomsErrorCode = agrc.KickMember( &roomsParticipant1, &roomsParticipant2, banReason );
  2383. RakAssert(roomsErrorCode==REC_SUCCESS);
  2384. // Join by filter
  2385. roomsErrorCode = agrc.JoinByFilter( gameIdentifier1, RMM_ANY_PLAYABLE, &roomsParticipant2, (RakNet::RoomID)-1, &roomQuery, &joinedRoomResult);
  2386. RakAssert(roomsErrorCode==REC_JOIN_BY_FILTER_NO_ROOMS);
  2387. RakNet::RakString banReasonOut;
  2388. roomsErrorCode = agrc.GetBanReason( room->GetID(), &room, roomsParticipant2.GetName(), &banReasonOut );
  2389. RakAssert(roomsErrorCode==REC_SUCCESS);
  2390. RakAssert(banReasonOut==banReason);
  2391. // Unban member
  2392. roomsErrorCode = agrc.UnbanMember( &roomsParticipant1, roomsParticipant2.GetName());
  2393. RakAssert(roomsErrorCode==REC_SUCCESS);
  2394. // Get ban reason
  2395. roomsErrorCode = agrc.GetBanReason( room->GetID(), &room, roomsParticipant2.GetName(), &banReasonOut );
  2396. RakAssert(roomsErrorCode==REC_GET_BAN_REASON_NOT_BANNED);
  2397. // Unban member again (should fail)
  2398. roomsErrorCode = agrc.UnbanMember( &roomsParticipant1, roomsParticipant2.GetName());
  2399. RakAssert(roomsErrorCode==REC_UNBAN_MEMBER_NOT_BANNED);
  2400. // Join by filter
  2401. roomsErrorCode = agrc.JoinByFilter( gameIdentifier1, RMM_ANY_PLAYABLE, &roomsParticipant2, (RakNet::RoomID)-1, &roomQuery, &joinedRoomResult);
  2402. RakAssert(roomsErrorCode==REC_SUCCESS);
  2403. // Set both members ready
  2404. roomsErrorCode = agrc.SetReadyStatus( &roomsParticipant1, true );
  2405. RakAssert(roomsErrorCode==REC_SUCCESS);
  2406. roomsErrorCode = agrc.SetReadyStatus( &roomsParticipant2, true );
  2407. RakAssert(roomsErrorCode==REC_SUCCESS);
  2408. // Set one member unready
  2409. roomsErrorCode = agrc.SetReadyStatus( &roomsParticipant1, false );
  2410. RakAssert(roomsErrorCode==REC_SUCCESS);
  2411. // Kick out 2nd member
  2412. roomsErrorCode = agrc.KickMember( &roomsParticipant1, &roomsParticipant2, "Don't like you too" );
  2413. RakAssert(roomsErrorCode==REC_SUCCESS);
  2414. // Unban member
  2415. roomsErrorCode = agrc.UnbanMember( &roomsParticipant1, roomsParticipant2.GetName());
  2416. RakAssert(roomsErrorCode==REC_SUCCESS);
  2417. // hide roomOutput
  2418. roomsErrorCode = agrc.SetHiddenFromSearches( &roomsParticipant1, true );
  2419. RakAssert(roomsErrorCode==REC_SUCCESS);
  2420. // Join by filter (should fail because hidden)
  2421. roomsErrorCode = agrc.JoinByFilter( gameIdentifier1, RMM_ANY_PLAYABLE, &roomsParticipant2, (RakNet::RoomID)-1, &roomQuery, &joinedRoomResult);
  2422. RakAssert(roomsErrorCode==REC_JOIN_BY_FILTER_NO_ROOMS);
  2423. }
粤ICP备19079148号