RoomsContainer.h 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  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. #ifndef __LOBBY_ROOM_H
  11. #define __LOBBY_ROOM_H
  12. #include "DS_Map.h"
  13. #include "DS_Table.h"
  14. #include "RoomsErrorCodes.h"
  15. #include "DS_List.h"
  16. #include "RakNetTypes.h"
  17. #include "IntervalTimer.h"
  18. #include "RoomTypes.h"
  19. namespace RakNet
  20. {
  21. class ProfanityFilter;
  22. class Room;
  23. class PerGameRoomList;
  24. class PerGameRoomsContainer;
  25. class BitStream;
  26. typedef unsigned int RoomID;
  27. struct QuickJoinUser;
  28. struct RoomMember;
  29. class AllGamesRoomsContainer;
  30. class RoomsParticipant
  31. {
  32. public:
  33. RoomsParticipant() {room=0; inQuickJoin=false;}
  34. ~RoomsParticipant() {}
  35. Room * GetRoom(void) const {return room;}
  36. void SetPerGameRoomsContainer(PerGameRoomsContainer *p) {perGameRoomsContainer=p;}
  37. void SetRoom(Room *_room) {room=_room; inQuickJoin=false;}
  38. void SetInQuickJoin(bool b) {inQuickJoin=b; if (b) room=0;}
  39. // Name is used for persistent invites and bans. Name should be unique among all participants or else the invites and bans will be applied to the wrong players
  40. RakNet::RakString GetName(void) const {return name;}
  41. void SetName(const char *str) {name = str;}
  42. void SetSystemAddress(const SystemAddress &sa) {systemAddress=sa;}
  43. SystemAddress GetSystemAddress(void) const {return systemAddress;}
  44. void SetGUID(RakNetGUID g) {guid=g;}
  45. RakNetGUID GetGUID(void) const {return guid;}
  46. PerGameRoomsContainer *GetPerGameRoomsContainer(void) const {return perGameRoomsContainer;}
  47. bool GetInQuickJoin(void) const {return inQuickJoin;}
  48. protected:
  49. RakNet::RakString name;
  50. SystemAddress systemAddress;
  51. RakNetGUID guid;
  52. Room *room;
  53. bool inQuickJoin;
  54. PerGameRoomsContainer *perGameRoomsContainer;
  55. };
  56. typedef RakNet::RakString GameIdentifier;
  57. enum RoomLockState
  58. {
  59. // Anyone can join or leave
  60. RLS_NOT_LOCKED,
  61. // Anyone can join as spectator or become spectator. New players are not allowed. You cannot leave spectator.
  62. RLS_PLAYERS_LOCKED,
  63. // No new players are allowed, and you cannot toggle spectator
  64. RLS_ALL_LOCKED
  65. };
  66. enum ParticipantCanJoinRoomResult
  67. {
  68. PCJRR_SUCCESS,
  69. PCJRR_BANNED,
  70. PCJRR_NO_PUBLIC_SLOTS,
  71. PCJRR_NO_PUBLIC_OR_RESERVED_SLOTS,
  72. PCJRR_NO_SPECTATOR_SLOTS,
  73. PCJRR_LOCKED,
  74. PCJRR_SLOT_ALREADY_USED,
  75. };
  76. struct Slots
  77. {
  78. Slots();
  79. ~Slots();
  80. unsigned int publicSlots;
  81. unsigned int reservedSlots;
  82. unsigned int spectatorSlots;
  83. unsigned int GetTotalSlots(void) const {return publicSlots+reservedSlots+spectatorSlots;}
  84. void Serialize(bool writeToBitstream, RakNet::BitStream *bitStream);
  85. RoomsErrorCode Validate(void) const;
  86. };
  87. struct InvitedUser
  88. {
  89. InvitedUser() {room=0; roomId=0; invitedAsSpectator=false;}
  90. Room *room;
  91. RoomID roomId;
  92. RakNet::RakString invitorName;
  93. SystemAddress invitorSystemAddress;
  94. RakNet::RakString target;
  95. RakNet::RakString subject;
  96. RakNet::RakString body;
  97. bool invitedAsSpectator;
  98. void Serialize(bool writeToBitstream, RakNet::BitStream *bitStream);
  99. };
  100. struct BannedUser
  101. {
  102. RakNet::RakString target;
  103. RakNet::RakString reason;
  104. void Serialize(bool writeToBitstream, RakNet::BitStream *bitStream);
  105. };
  106. struct RemoveUserResult
  107. {
  108. RemoveUserResult();
  109. ~RemoveUserResult();
  110. // Why return a deleted pointer?
  111. // RoomsParticipant *removedUser;
  112. bool removedFromQuickJoin;
  113. bool removedFromRoom;
  114. SystemAddress removedUserAddress;
  115. RakNet::RakString removedUserName;
  116. // Following members only apply if removedFromRoom==true
  117. Room *room;
  118. RoomID roomId;
  119. bool gotNewModerator; // If you were the moderator before, this is true
  120. DataStructures::List<InvitedUser> clearedInvitations; // If invitations were cleared when you leave, these are the invitations
  121. bool roomDestroyed; // Up to caller to deallocate
  122. QuickJoinUser *qju;
  123. void Serialize(bool writeToBitstream, RakNet::BitStream *bitStream);
  124. };
  125. struct RoomMemberDescriptor
  126. {
  127. RakNet::RakString name;
  128. RoomMemberMode roomMemberMode;
  129. bool isReady;
  130. // Filled externally
  131. SystemAddress systemAddress;
  132. RakNetGUID guid;
  133. void FromRoomMember(RoomMember *roomMember);
  134. void Serialize(bool writeToBitstream, RakNet::BitStream *bitStream);
  135. };
  136. struct NetworkedRoomCreationParameters
  137. {
  138. NetworkedRoomCreationParameters() {hiddenFromSearches=false; destroyOnModeratorLeave=false; autoLockReadyStatus=false; inviteToRoomPermission=INVITE_MODE_ANYONE_CAN_INVITE; inviteToSpectatorSlotPermission=INVITE_MODE_ANYONE_CAN_INVITE; clearInvitesOnNewModerator=false;}
  139. // Checked by Validate
  140. Slots slots;
  141. bool hiddenFromSearches;
  142. bool destroyOnModeratorLeave;
  143. bool autoLockReadyStatus; // When everyone is ready and (the room is full or the room is locked), don't allow users to set unready.
  144. enum SendInvitePermission
  145. {
  146. INVITE_MODE_ANYONE_CAN_INVITE,
  147. INVITE_MODE_MODERATOR_CAN_INVITE,
  148. INVITE_MODE_PUBLIC_SLOTS_CAN_INVITE,
  149. INVITE_MODE_RESERVED_SLOTS_CAN_INVITE,
  150. INVITE_MODE_SPECTATOR_SLOTS_CAN_INVITE,
  151. INVITE_MODE_MODERATOR_OR_PUBLIC_SLOTS_CAN_INVITE,
  152. INVITE_MODE_MODERATOR_OR_PUBLIC_OR_RESERVED_SLOTS_CAN_INVITE,
  153. } inviteToRoomPermission, inviteToSpectatorSlotPermission;
  154. bool clearInvitesOnNewModerator; // Leave or change
  155. RakNet::RakString roomName;
  156. void Serialize(bool writeToBitstream, RakNet::BitStream *bitStream);
  157. static const char *SendInvitePermissionToEnum(SendInvitePermission e);
  158. };
  159. struct RoomDescriptor
  160. {
  161. DataStructures::List<RoomMemberDescriptor> roomMemberList;
  162. DataStructures::List<BannedUser> banList;
  163. RoomLockState roomLockState;
  164. RoomID lobbyRoomId;
  165. bool autoLockReadyStatus;
  166. bool hiddenFromSearches;
  167. NetworkedRoomCreationParameters::SendInvitePermission inviteToRoomPermission;
  168. NetworkedRoomCreationParameters::SendInvitePermission inviteToSpectatorSlotPermission;
  169. DataStructures::Table roomProperties;
  170. DataStructures::Table::Cell *GetProperty(const char* columnName)
  171. {
  172. return roomProperties.GetRowByIndex(0,0)->cells[roomProperties.ColumnIndex(columnName)];
  173. }
  174. DataStructures::Table::Cell *GetProperty(int index)
  175. {
  176. return roomProperties.GetRowByIndex(0,0)->cells[index];
  177. }
  178. void Clear(void)
  179. {
  180. roomMemberList.Clear(false, _FILE_AND_LINE_);
  181. banList.Clear(false, _FILE_AND_LINE_);
  182. roomProperties.Clear();
  183. }
  184. void FromRoom(Room *room, AllGamesRoomsContainer *agrc);
  185. void Serialize(bool writeToBitstream, RakNet::BitStream *bitStream);
  186. };
  187. struct JoinedRoomResult
  188. {
  189. JoinedRoomResult() {roomOutput=0; acceptedInvitor=0; agrc=0; joiningMember=0;}
  190. ~JoinedRoomResult() {}
  191. Room* roomOutput;
  192. RoomDescriptor roomDescriptor;
  193. RoomsParticipant* acceptedInvitor;
  194. RakNet::RakString acceptedInvitorName;
  195. SystemAddress acceptedInvitorAddress;
  196. RoomsParticipant* joiningMember;
  197. RakNet::RakString joiningMemberName;
  198. SystemAddress joiningMemberAddress;
  199. RakNetGUID joiningMemberGuid;
  200. // Needed to serialize
  201. AllGamesRoomsContainer *agrc;
  202. void Serialize(bool writeToBitstream, RakNet::BitStream *bitStream );
  203. };
  204. struct RoomCreationParameters
  205. {
  206. RoomCreationParameters();
  207. ~RoomCreationParameters();
  208. NetworkedRoomCreationParameters networkedRoomCreationParameters;
  209. // Not checked
  210. RoomsParticipant* firstUser;
  211. GameIdentifier gameIdentifier;
  212. // Output parameters:
  213. // Was the room created?
  214. bool createdRoom;
  215. Room *roomOutput;
  216. // May return REC_ROOM_CREATION_PARAMETERS_* or REC_SUCCESS
  217. RoomsErrorCode Validate(
  218. const DataStructures::List<RakNet::RakString> &otherRoomNames,
  219. ProfanityFilter *profanityFilter) const;
  220. };
  221. struct RoomMember
  222. {
  223. RoomMember();
  224. ~RoomMember();
  225. RoomsParticipant* roomsParticipant;
  226. RoomMemberMode roomMemberMode;
  227. RakNet::TimeMS joinTime;
  228. bool isReady;
  229. // Internal - set to false when a new member is added. When the other members have been told about this member, it is set to true
  230. bool newMemberNotificationProcessed;
  231. };
  232. struct KickedUser
  233. {
  234. RoomsParticipant* roomsParticipant;
  235. RakNet::RakString reason;
  236. };
  237. struct RoomQuery
  238. {
  239. RoomQuery();
  240. ~RoomQuery();
  241. // Point to an externally allocated array of FilterQuery, or use the helper functions below to use a static array (not threadsafe to use the static array)
  242. DataStructures::Table::FilterQuery *queries;
  243. // Size of the queries array
  244. unsigned int numQueries;
  245. // Not used
  246. bool queriesAllocated;
  247. // Helper functions
  248. // Easier to use, but not threadsafe
  249. void AddQuery_NUMERIC(const char *columnName, double numericValue, DataStructures::Table::FilterQueryType op=DataStructures::Table::QF_EQUAL);
  250. void AddQuery_STRING(const char *columnName, const char *charValue, DataStructures::Table::FilterQueryType op=DataStructures::Table::QF_EQUAL);
  251. void AddQuery_BINARY(const char *columnName, const char *input, int inputLength, DataStructures::Table::FilterQueryType op=DataStructures::Table::QF_EQUAL);
  252. void AddQuery_POINTER(const char *columnName, void *ptr, DataStructures::Table::FilterQueryType op=DataStructures::Table::QF_EQUAL);
  253. RoomsErrorCode Validate(void);
  254. void Serialize(bool writeToBitstream, RakNet::BitStream *bitStream);
  255. /// \internal
  256. void SetQueriesToStatic(void);
  257. private:
  258. static DataStructures::Table::FilterQuery fq[32];
  259. static DataStructures::Table::Cell cells[32];
  260. void SetupNextQuery(const char *columnName,DataStructures::Table::FilterQueryType op);
  261. };
  262. struct NetworkedQuickJoinUser
  263. {
  264. NetworkedQuickJoinUser() {timeout=60000; minimumPlayers=2;}
  265. // How long to wait for
  266. RakNet::TimeMS timeout;
  267. // What queries to join the room on.
  268. RoomQuery query;
  269. // Minimum number of slots to join
  270. int minimumPlayers;
  271. void Serialize(bool writeToBitstream, RakNet::BitStream *bitStream);
  272. };
  273. struct QuickJoinUser
  274. {
  275. QuickJoinUser();
  276. ~QuickJoinUser();
  277. NetworkedQuickJoinUser networkedQuickJoinUser;
  278. // Total amount of time spent waiting
  279. RakNet::TimeMS totalTimeWaiting;
  280. // Which user
  281. RoomsParticipant* roomsParticipant;
  282. static int SortByTotalTimeWaiting( QuickJoinUser* const &key, QuickJoinUser* const &data );
  283. static int SortByMinimumSlots( QuickJoinUser* const &key, QuickJoinUser* const &data );
  284. };
  285. int RoomPriorityComp( Room * const &key, Room * const &data );
  286. // PerGameRoomsContainer, mapped by game id
  287. class AllGamesRoomsContainer
  288. {
  289. public:
  290. AllGamesRoomsContainer();
  291. ~AllGamesRoomsContainer();
  292. static void UnitTest(void);
  293. RoomsErrorCode CreateRoom(RoomCreationParameters *roomCreationParameters,
  294. ProfanityFilter *profanityFilter);
  295. // Enters a room based on the search queries. If no rooms are available to join, will create a room instead
  296. RoomsErrorCode EnterRoom(RoomCreationParameters *roomCreationParameters,
  297. RoomMemberMode roomMemberMode,
  298. ProfanityFilter *profanityFilter,
  299. RoomQuery *query,
  300. JoinedRoomResult *joinRoomResult);
  301. // Attempts to join a room by search query filters
  302. // Returns REC_JOIN_BY_FILTER_*
  303. RoomsErrorCode JoinByFilter(GameIdentifier gameIdentifier, RoomMemberMode roomMemberMode, RoomsParticipant* roomsParticipant, RoomID lastRoomJoined, RoomQuery *query, JoinedRoomResult *joinRoomResult);
  304. // Add a new title to host games with
  305. RoomsErrorCode AddTitle(GameIdentifier gameIdentifier);
  306. // Get all pending invites to you
  307. RoomsErrorCode GetInvitesToParticipant(RoomsParticipant* roomsParticipant, DataStructures::List<InvitedUser*> &invites);
  308. RoomsErrorCode RemoveUser(RoomsParticipant* roomsParticipant, RemoveUserResult *removeMemberResult);
  309. // ROOMS OPERATIONS, implicit room
  310. RoomsErrorCode SendInvite(RoomsParticipant* roomsParticipant, RoomsParticipant* inviteeId, bool inviteToSpectatorSlot, RakNet::RakString subject, RakNet::RakString body);
  311. RoomsErrorCode AcceptInvite(RoomID roomId, Room **room, RoomsParticipant* roomsParticipant, RakNet::RakString inviteSender);
  312. RoomsErrorCode StartSpectating(RoomsParticipant* roomsParticipant);
  313. RoomsErrorCode StopSpectating(RoomsParticipant* roomsParticipant);
  314. RoomsErrorCode GrantModerator(RoomsParticipant* roomsParticipant, RoomsParticipant *newModerator, DataStructures::List<InvitedUser> &clearedInvites);
  315. RoomsErrorCode ChangeSlotCounts(RoomsParticipant* roomsParticipant, Slots slots);
  316. RoomsErrorCode SetCustomRoomProperties(RoomsParticipant* roomsParticipant, DataStructures::Table *table);
  317. RoomsErrorCode ChangeRoomName(RoomsParticipant* roomsParticipant, RakNet::RakString newRoomName, ProfanityFilter *profanityFilter);
  318. RoomsErrorCode SetHiddenFromSearches(RoomsParticipant* roomsParticipant, bool _hiddenFromSearches);
  319. RoomsErrorCode SetDestroyOnModeratorLeave(RoomsParticipant* roomsParticipant, bool destroyOnModeratorLeave);
  320. RoomsErrorCode SetReadyStatus(RoomsParticipant* roomsParticipant, bool isReady);
  321. RoomsErrorCode GetReadyStatus( RoomID roomId, Room **room, DataStructures::List<RoomsParticipant*> &readyUsers, DataStructures::List<RoomsParticipant*> &unreadyUsers);
  322. RoomsErrorCode SetRoomLockState(RoomsParticipant* roomsParticipant, RoomLockState _roomLockState);
  323. RoomsErrorCode GetRoomLockState(RoomID roomId, Room **room, RoomLockState *roomLockState);
  324. RoomsErrorCode AreAllMembersReady(RoomID roomId, Room **room, bool *allReady);
  325. RoomsErrorCode KickMember(RoomsParticipant* roomsParticipant, RoomsParticipant *kickedParticipant, RakNet::RakString reason);
  326. RoomsErrorCode UnbanMember(RoomsParticipant* roomsParticipant, RakNet::RakString name);
  327. RoomsErrorCode GetBanReason( RoomID lobbyRoomId, Room **room, RakNet::RakString name, RakNet::RakString *reason);
  328. RoomsErrorCode LeaveRoom(RoomsParticipant* roomsParticipant, RemoveUserResult *removeUserResult);
  329. //RoomsErrorCode GetKickReason(RoomsParticipant* roomsParticipant, RakNet::RakString *kickReason);
  330. void GetRoomProperties(RoomID roomId, Room **room, DataStructures::Table *table);
  331. // Quick join algorithm:
  332. //
  333. // -- ROOM JOIN --
  334. //
  335. // For all rooms:
  336. // 1. Clear all quickJoinWorkingList from all rooms
  337. // For all quick join members
  338. // 2. Use RoomPrioritySort to get all rooms they can potentially join
  339. // 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
  340. // For all rooms:
  341. // 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.
  342. //
  343. // -- ROOM CREATE --
  344. //
  345. // 5. Sort quick join members by minimumPlayers, excluding members where minimumPlayers > total number of quick join members
  346. // From greatest minimumPlayers to least
  347. // 6. If the current member created a room, find out how many subsequent members would join based on the custom filter
  348. // 7. If this satisfies minimumPlayers, have that user create a room and those subsequent members join.
  349. //
  350. // -- EXPIRE
  351. //
  352. // 5. Remove from list if timeout has expired.
  353. // 6. Return results of operation (List<timeoutExpired>, List<joinedARoom>, List<RoomsThatWereJoined>
  354. //
  355. // Returns false if processing skipped due to optimization timer
  356. RoomsErrorCode ProcessQuickJoins(
  357. DataStructures::List<QuickJoinUser*> &timeoutExpired,
  358. DataStructures::List<JoinedRoomResult> &joinedRoomMembers,
  359. DataStructures::List<QuickJoinUser*> &dereferencedPointers,
  360. RakNet::TimeMS elapsedTime);
  361. // Quick join - Store a list of all members waiting to quick join.
  362. // Quick join ends when
  363. // 1. An existing room can be fully populated using waiting quick join members.
  364. // 2. Enough quick join members are waiting that a new room can be created with the number of members >= minimumPlayers for all members
  365. // It also ends if timeToWaitMS expires.
  366. // Returns REC_ADD_TO_QUICK_JOIN_*
  367. // Passed pointer is stored on REC_SUCCESS, allocate, and do not deallocate unless not successful
  368. RoomsErrorCode AddUserToQuickJoin(GameIdentifier gameIdentifier, QuickJoinUser *quickJoinMember);
  369. // Returns REC_REMOVE_FROM_QUICK_JOIN_*
  370. RoomsErrorCode RemoveUserFromQuickJoin(RoomsParticipant* roomsParticipant, QuickJoinUser **qju);
  371. // Is this user in quick join?
  372. bool IsInQuickJoin(RoomsParticipant* roomsParticipant);
  373. // Get all rooms for a certain title
  374. static int RoomsSortByName( Room* const &key, Room* const &data );
  375. RoomsErrorCode SearchByFilter( GameIdentifier gameIdentifier, RoomsParticipant* roomsParticipant, RoomQuery *roomQuery, DataStructures::OrderedList<Room*, Room*, RoomsSortByName> &roomsOutput, bool onlyJoinable );
  376. // Deallocate a room
  377. void DestroyRoomIfDead(Room *room);
  378. // If a handle changes, you have to tell the system here. Otherwise ban and invite names will be out of synch
  379. // System does not verify that the handle is not currently in use since it does not necessarily know about all online players
  380. // This is an invariant up to the caller to uphold. Failure to do so will result in the wrong players being banned or invited
  381. void ChangeHandle(RakNet::RakString oldHandle, RakNet::RakString newHandle);
  382. unsigned int GetPropertyIndex(RoomID lobbyRoomId, const char *propertyName) const;
  383. DataStructures::Map<GameIdentifier, PerGameRoomsContainer*> perGamesRoomsContainers;
  384. Room * GetRoomByLobbyRoomID(RoomID lobbyRoomID);
  385. Room * GetRoomByName(RakNet::RakString roomName);
  386. protected:
  387. RoomID nextRoomId;
  388. };
  389. class PerGameRoomsContainer
  390. {
  391. public:
  392. PerGameRoomsContainer();
  393. ~PerGameRoomsContainer();
  394. // Has pointer column to class Room
  395. DataStructures::Table roomsTable;
  396. // Members that are waiting to quick join
  397. DataStructures::List<QuickJoinUser*> quickJoinList;
  398. static int RoomsSortByTimeThenTotalSlots( Room* const &key, Room* const &data );
  399. protected:
  400. RoomsErrorCode CreateRoom(RoomCreationParameters *roomCreationParameters,
  401. ProfanityFilter *profanityFilter,
  402. RoomID lobbyRoomId,
  403. bool validate);
  404. RoomsErrorCode LeaveRoom(RoomsParticipant* roomsParticipant, bool *gotNewModerator);
  405. RoomsErrorCode JoinByFilter(RoomMemberMode roomMemberMode, RoomsParticipant* roomsParticipant, RoomID lastRoomJoined, RoomQuery *query, JoinedRoomResult *joinRoomResult);
  406. RoomsErrorCode AddUserToQuickJoin(QuickJoinUser *quickJoinMember);
  407. RoomsErrorCode RemoveUserFromQuickJoin(RoomsParticipant* roomsParticipant, QuickJoinUser **qju);
  408. bool IsInQuickJoin(RoomsParticipant* roomsParticipant);
  409. unsigned int GetQuickJoinIndex(RoomsParticipant* roomsParticipant);
  410. void GetRoomNames(DataStructures::List<RakNet::RakString> &roomNames);
  411. void GetAllRooms(DataStructures::List<Room*> &rooms);
  412. // Looks for a particular room that has a particular ID
  413. Room * GetRoomByLobbyRoomID(RoomID lobbyRoomID);
  414. Room * GetRoomByName(RakNet::RakString roomName);
  415. RoomsErrorCode GetInvitesToParticipant(RoomsParticipant* roomsParticipant, DataStructures::List<InvitedUser*> &invites);
  416. bool DestroyRoomIfDead(Room *room);
  417. void ChangeHandle(RakNet::RakString oldHandle, RakNet::RakString newHandle);
  418. unsigned ProcessQuickJoins( DataStructures::List<QuickJoinUser*> &timeoutExpired,
  419. DataStructures::List<JoinedRoomResult> &joinedRooms,
  420. DataStructures::List<QuickJoinUser*> &dereferencedPointers,
  421. RakNet::TimeMS elapsedTime,
  422. RoomID startingRoomId);
  423. // Sort an input list of rooms
  424. // Rooms are sorted by time created (longest is higher priority). If within one minute, then subsorted by total playable slot count (lower is higher priority).
  425. // When using EnterRoom or JoinByFilter, record the last roomOutput joined, and try to avoid rejoining the same roomOutput just left
  426. void RoomPrioritySort( RoomsParticipant* roomsParticipant, RoomQuery *roomQuery, DataStructures::OrderedList<Room*, Room*, RoomsSortByTimeThenTotalSlots> &roomsOutput );
  427. RoomsErrorCode SearchByFilter( RoomsParticipant* roomsParticipant, RoomQuery *roomQuery, DataStructures::OrderedList<Room*, Room*, AllGamesRoomsContainer::RoomsSortByName> &roomsOutput, bool onlyJoinable );
  428. friend class AllGamesRoomsContainer;
  429. IntervalTimer nextQuickJoinProcess;
  430. };
  431. // Holds all the members of a particular roomOutput
  432. class Room
  433. {
  434. public:
  435. Room( RoomID _roomId, RoomCreationParameters *roomCreationParameters, DataStructures::Table::Row *_row, RoomsParticipant* roomsParticipant );
  436. ~Room();
  437. RoomsErrorCode SendInvite(RoomsParticipant* roomsParticipant, RoomsParticipant* inviteeId, bool inviteToSpectatorSlot, RakNet::RakString subject, RakNet::RakString body);
  438. RoomsErrorCode AcceptInvite(RoomsParticipant* roomsParticipant, RakNet::RakString inviteSender);
  439. RoomsErrorCode StartSpectating(RoomsParticipant* roomsParticipant);
  440. RoomsErrorCode StopSpectating(RoomsParticipant* roomsParticipant);
  441. RoomsErrorCode GrantModerator(RoomsParticipant* roomsParticipant, RoomsParticipant *newModerator, DataStructures::List<InvitedUser> &clearedInvites);
  442. RoomsErrorCode ChangeSlotCounts(RoomsParticipant* roomsParticipant, Slots slots);
  443. RoomsErrorCode SetCustomRoomProperties(RoomsParticipant* roomsParticipant, DataStructures::Table *table);
  444. RoomsErrorCode ChangeRoomName(RoomsParticipant* roomsParticipant, RakNet::RakString newRoomName, ProfanityFilter *profanityFilter);
  445. RoomsErrorCode SetHiddenFromSearches(RoomsParticipant* roomsParticipant, bool _hiddenFromSearches);
  446. RoomsErrorCode SetDestroyOnModeratorLeave(RoomsParticipant* roomsParticipant, bool destroyOnModeratorLeave);
  447. RoomsErrorCode SetReadyStatus(RoomsParticipant* roomsParticipant, bool isReady);
  448. RoomsErrorCode GetReadyStatus(DataStructures::List<RoomsParticipant*> &readyUsers, DataStructures::List<RoomsParticipant*> &unreadyUsers);
  449. RoomsErrorCode SetRoomLockState(RoomsParticipant* roomsParticipant, RoomLockState _roomLockState);
  450. RoomsErrorCode GetRoomLockState(RoomLockState *_roomLockState);
  451. RoomsErrorCode AreAllMembersReady(unsigned int exceptThisIndex, bool *allReady);
  452. RoomsErrorCode KickMember(RoomsParticipant* roomsParticipant, RoomsParticipant *kickedParticipant, RakNet::RakString reason);
  453. RoomsErrorCode UnbanMember(RoomsParticipant* roomsParticipant, RakNet::RakString name);
  454. RoomsErrorCode GetBanReason(RakNet::RakString name, RakNet::RakString *reason);
  455. RoomsErrorCode LeaveRoom(RoomsParticipant* roomsParticipant, RemoveUserResult *removeUserResult);
  456. //RoomsErrorCode GetKickReason(RoomsParticipant* roomsParticipant, RakNet::RakString *kickReason);
  457. RoomsErrorCode JoinByFilter(RoomsParticipant* roomsParticipant, RoomMemberMode roomMemberMode, JoinedRoomResult *joinRoomResult);
  458. RoomsErrorCode JoinByQuickJoin(RoomsParticipant* roomsParticipant, RoomMemberMode roomMemberMode, JoinedRoomResult *joinRoomResult);
  459. bool IsHiddenToParticipant(RoomsParticipant* roomsParticipant) const;
  460. // Can this user join this roomOutput?
  461. ParticipantCanJoinRoomResult ParticipantCanJoinAsPlayer( RoomsParticipant* roomsParticipant, bool asSpectator, bool checkHasInvite );
  462. ParticipantCanJoinRoomResult ParticipantCanJoinRoom( RoomsParticipant* roomsParticipant, bool asSpectator, bool checkHasInvite );
  463. // Returns true if there are only spectators, or nobody at all
  464. bool IsRoomDead(void) const;
  465. RoomsErrorCode GetInvitesToParticipant(RoomsParticipant* roomsParticipant, DataStructures::List<InvitedUser*> &invites);
  466. RoomsParticipant* GetModerator(void) const;
  467. // Gets the roomOutput ID
  468. RoomID GetID(void) const;
  469. double GetNumericProperty(RoomID lobbyRoomId, const char *propertyName) const;
  470. const char *GetStringProperty(RoomID lobbyRoomId, const char *propertyName) const;
  471. double GetNumericProperty(int index) const;
  472. const char *GetStringProperty(int index) const;
  473. void SetNumericProperty(int index, double value);
  474. void SetStringProperty(int index, const char *value);
  475. // Public for easy access
  476. DataStructures::List<RoomMember*> roomMemberList;
  477. DataStructures::List<InvitedUser> inviteList;
  478. DataStructures::List<BannedUser> banList;
  479. // Don't store - slow because when removing users I have to iterate through every room
  480. // DataStructures::List<KickedUser> kickedList;
  481. // Internal
  482. DataStructures::List<QuickJoinUser*> quickJoinWorkingList;
  483. static void UpdateRowSlots( DataStructures::Table::Row* row, Slots *totalSlots, Slots *usedSlots);
  484. void ChangeHandle(RakNet::RakString oldHandle, RakNet::RakString newHandle);
  485. protected:
  486. Room();
  487. // Updates the table row
  488. RoomsErrorCode RemoveUser(RoomsParticipant* roomsParticipant,RemoveUserResult *removeUserResult);
  489. bool IsRoomLockedToSpectators(void) const;
  490. bool IsRoomLockedToPlayers(void) const;
  491. bool IsInRoom(RoomsParticipant* roomsParticipant) const;
  492. bool HasInvite(RakNet::RakString roomsParticipant);
  493. unsigned int GetRoomIndex(RoomsParticipant* roomsParticipant) const;
  494. unsigned int GetBannedIndex(RakNet::RakString username) const;
  495. unsigned int GetInviteIndex(RakNet::RakString invitee, RakNet::RakString invitor) const;
  496. unsigned int GetFirstInviteIndex(RakNet::RakString invitee) const;
  497. bool AreAllPlayableSlotsFilled(void) const;
  498. bool HasOpenPublicSlots(void) const;
  499. bool HasOpenReservedSlots(void) const;
  500. bool HasOpenSpectatorSlots(void) const;
  501. void UpdateUsedSlots( void );
  502. void UpdateUsedSlots( Slots *totalSlots, Slots *usedSlots );
  503. static void UpdateUsedSlots( DataStructures::Table::Row* tableRow, Slots *totalSlots, Slots *usedSlots );
  504. Slots GetTotalSlots(void) const;
  505. void SetTotalSlots(Slots *totalSlots);
  506. Slots GetUsedSlots(void) const;
  507. RoomLockState roomLockState;
  508. friend struct RoomDescriptor;
  509. friend class PerGameRoomsContainer;
  510. friend class AllGamesRoomsContainer;
  511. RoomID lobbyRoomId;
  512. DataStructures::Table::Row *tableRow;
  513. bool autoLockReadyStatus;
  514. bool hiddenFromSearches;
  515. // bool destroyOnModeratorLeave;
  516. bool clearInvitesOnNewModerator;
  517. NetworkedRoomCreationParameters::SendInvitePermission inviteToRoomPermission, inviteToSpectatorSlotPermission;
  518. bool roomDestroyed;
  519. };
  520. } // namespace Lobby2
  521. #endif
粤ICP备19079148号