This commit is contained in:
2025-11-24 14:19:51 +05:30
commit f5c1412b28
6734 changed files with 1527575 additions and 0 deletions

View File

@ -0,0 +1,38 @@
/*
* Original work: Copyright (c) 2014, Oculus VR, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* RakNet License.txt file in the licenses directory of this source tree. An additional grant
* of patent rights can be found in the RakNet Patents.txt file in the same directory.
*
*
* Modified work: Copyright (c) 2017, SLikeSoft UG (haftungsbeschränkt)
*
* This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
* license found in the license.txt file in the root directory of this source tree.
*/
#include "IntervalTimer.h"
void IntervalTimer::SetPeriod(SLNet::TimeMS period) {basePeriod=period; remaining=0;}
bool IntervalTimer::UpdateInterval(SLNet::TimeMS elapsed)
{
if (elapsed >= remaining)
{
SLNet::TimeMS difference = elapsed-remaining;
if (difference >= basePeriod)
{
remaining=basePeriod;
}
else
{
remaining=basePeriod-difference;
}
return true;
}
remaining-=elapsed;
return false;
}

View File

@ -0,0 +1,29 @@
/*
* Original work: Copyright (c) 2014, Oculus VR, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* RakNet License.txt file in the licenses directory of this source tree. An additional grant
* of patent rights can be found in the RakNet Patents.txt file in the same directory.
*
*
* Modified work: Copyright (c) 2017, SLikeSoft UG (haftungsbeschränkt)
*
* This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
* license found in the license.txt file in the root directory of this source tree.
*/
#ifndef __INTERVAL_TIMER_H
#define __INTERVAL_TIMER_H
#include "slikenet/types.h"
struct IntervalTimer
{
void SetPeriod(SLNet::TimeMS period);
bool UpdateInterval(SLNet::TimeMS elapsed);
SLNet::TimeMS basePeriod, remaining;
};
#endif

View File

@ -0,0 +1,164 @@
/*
* Original work: Copyright (c) 2014, Oculus VR, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* RakNet License.txt file in the licenses directory of this source tree. An additional grant
* of patent rights can be found in the RakNet Patents.txt file in the same directory.
*
*
* Modified work: Copyright (c) 2016-2018, SLikeSoft UG (haftungsbeschränkt)
*
* This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
* license found in the license.txt file in the root directory of this source tree.
*/
#include "ProfanityFilter.h"
#include "slikenet/Rand.h"
#include "slikenet/assert.h"
#include "slikenet/LinuxStrings.h"
#include "slikenet/linux_adapter.h"
#include "slikenet/osx_adapter.h"
#if defined(_WIN32)
#include <malloc.h> // alloca
#elif (defined(__GNUC__) || defined(__GCCXML__))
#include <alloca.h>
#else
#endif
using namespace SLNet;
char ProfanityFilter::BANCHARS[] = "!@#$%^&*()";
char ProfanityFilter::WORDCHARS[] = "abcdefghijklmnopqrstuvwxyz0123456789";
ProfanityFilter::ProfanityFilter()
{
}
ProfanityFilter::~ProfanityFilter()
{
}
char ProfanityFilter::RandomBanChar()
{
return BANCHARS[randomMT() % (sizeof(BANCHARS) - 1)];
}
bool ProfanityFilter::HasProfanity(const char *str)
{
return FilterProfanity(str, 0, 0,false) > 0;
}
int ProfanityFilter::FilterProfanity(const char *input, char *output, bool filter)
{
if (input == 0 || input[0] == 0)
return 0;
int count = 0;
char* b = (char *)alloca(strlen(input) + 1);
strcpy_s(b, strlen(input) + 1, input);
_strlwr(b);
char *start = b;
if (output)
strcpy(output, input);
start = strpbrk(start, WORDCHARS);
while (start != 0)
{
size_t len = strspn(start, WORDCHARS);
if (len > 0)
{
// we a have a word - let's check if it's a BAAAD one
char saveChar = start[len];
start[len] = '\0';
// loop through profanity list
for (unsigned int i = 0, size = words.Size(); i < size; i++)
{
if (_stricmp(start, words[i].C_String()) == 0)
{
count++;
// size_t len = words[i].size();
if (filter && output)
{
for (unsigned int j = 0; j < len; j++)
{
output[start + j - b] = RandomBanChar();
}
}
break;
}
}
start[len] = saveChar;
}
start += len;
start = strpbrk(start, WORDCHARS);
}
return count;
}
int ProfanityFilter::FilterProfanity(const char *input, char *output, size_t outputLength, bool filter)
{
if (input==0 || input[0]==0)
return 0;
int count = 0;
char* b = (char *) alloca(strlen(input) + 1);
strcpy_s(b, strlen(input) + 1, input);
_strlwr(b);
char *start = b;
if (output)
strcpy_s(output,outputLength,input);
start = strpbrk(start, WORDCHARS);
while (start != 0)
{
size_t len = strspn(start, WORDCHARS);
if (len > 0)
{
// we a have a word - let's check if it's a BAAAD one
char saveChar = start[len];
start[len] = '\0';
// loop through profanity list
for (unsigned int i = 0, size = words.Size(); i < size; i++)
{
if (_stricmp(start, words[i].C_String()) == 0)
{
count++;
// size_t len = words[i].size();
if (filter && output)
{
for (unsigned int j = 0; j < len; j++)
{
output[start + j - b] = RandomBanChar();
}
}
break;
}
}
start[len] = saveChar;
}
start += len;
start = strpbrk(start, WORDCHARS);
}
return count;
}
int ProfanityFilter::Count()
{
return words.Size();
}
void ProfanityFilter::AddWord(SLNet::RakString newWord)
{
words.Insert(newWord, _FILE_AND_LINE_ );
}

View File

@ -0,0 +1,52 @@
/*
* Original work: Copyright (c) 2014, Oculus VR, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* RakNet License.txt file in the licenses directory of this source tree. An additional grant
* of patent rights can be found in the RakNet Patents.txt file in the same directory.
*
*
* Modified work: Copyright (c) 2016-2018, SLikeSoft UG (haftungsbeschränkt)
*
* This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
* license found in the license.txt file in the root directory of this source tree.
*/
#ifndef __PROFANITY_FILTER__H__
#define __PROFANITY_FILTER__H__
#include "slikenet/DS_List.h"
#include "slikenet/string.h"
namespace SLNet {
class ProfanityFilter
{
public:
ProfanityFilter();
~ProfanityFilter();
// Returns true if the string has profanity, false if not.
bool HasProfanity(const char *str);
// Removes profanity. Returns number of occurrences of profanity matches (including 0)
int FilterProfanity(const char *input, char *output, bool filter = true);
int FilterProfanity(const char *input, char *output, size_t outputLength, bool filter = true);
// Number of profanity words loaded
int Count();
void AddWord(SLNet::RakString newWord);
private:
DataStructures::List<SLNet::RakString> words;
char RandomBanChar();
static char BANCHARS[];
static char WORDCHARS[];
};
} // namespace SLNet
#endif // __PROFANITY__H__

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2014, Oculus VR, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* RakNet License.txt file in the licenses directory of this source tree. An additional grant
* of patent rights can be found in the RakNet Patents.txt file in the same directory.
*
*/
#include "RoomTypes.h"
const char *RoomMemberModeToEnum(RoomMemberMode e)
{
switch (e)
{
case RMM_MODERATOR:
return "RMM_MODERATOR";
case RMM_PUBLIC:
return "RMM_PUBLIC";
case RMM_RESERVED:
return "RMM_RESERVED";
case RMM_SPECTATOR_PUBLIC:
return "RMM_SPECTATOR_PUBLIC";
case RMM_SPECTATOR_RESERVED:
return "RMM_SPECTATOR_RESERVED";
case RMM_ANY_PLAYABLE:
return "RMM_ANY_PLAYABLE";
case RMM_ANY_SPECTATOR:
return "RMM_ANY_SPECTATOR";
}
return "Error in RoomMemberModeToEnum";
}
static DefaultRoomColumns defaultRoomColumns[DefaultRoomColumns::TC_TABLE_COLUMNS_COUNT] =
{
{DefaultRoomColumns::TC_TITLE_NAME, "Title name", DataStructures::Table::STRING},
{DefaultRoomColumns::TC_TITLE_ID, "Title id", DataStructures::Table::NUMERIC},
{DefaultRoomColumns::TC_ROOM_NAME, "Room name", DataStructures::Table::STRING},
{DefaultRoomColumns::TC_ROOM_ID, "Room id", DataStructures::Table::NUMERIC},
{DefaultRoomColumns::TC_TOTAL_SLOTS, "Total slots", DataStructures::Table::NUMERIC},
{DefaultRoomColumns::TC_TOTAL_PUBLIC_PLUS_RESERVED_SLOTS, "Total Public plus reserved slots", DataStructures::Table::NUMERIC},
{DefaultRoomColumns::TC_USED_SLOTS, "Used slots", DataStructures::Table::NUMERIC},
{DefaultRoomColumns::TC_USED_PUBLIC_PLUS_RESERVED_SLOTS, "Used public plus reserved slots", DataStructures::Table::NUMERIC},
{DefaultRoomColumns::TC_REMAINING_SLOTS, "Remaining slots", DataStructures::Table::NUMERIC},
{DefaultRoomColumns::TC_REMAINING_PUBLIC_PLUS_RESERVED_SLOTS, "Remaining public plus reserved slots", DataStructures::Table::NUMERIC},
{DefaultRoomColumns::TC_TOTAL_PUBLIC_SLOTS, "Total public slots", DataStructures::Table::NUMERIC},
{DefaultRoomColumns::TC_TOTAL_RESERVED_SLOTS, "Total reserved slots", DataStructures::Table::NUMERIC},
{DefaultRoomColumns::TC_TOTAL_SPECTATOR_SLOTS, "Total spectator slots", DataStructures::Table::NUMERIC},
{DefaultRoomColumns::TC_USED_PUBLIC_SLOTS, "Used public slots", DataStructures::Table::NUMERIC},
{DefaultRoomColumns::TC_USED_RESERVED_SLOTS, "Used reserved slots", DataStructures::Table::NUMERIC},
{DefaultRoomColumns::TC_USED_SPECTATOR_SLOTS, "Used spectator slots", DataStructures::Table::NUMERIC},
{DefaultRoomColumns::TC_REMAINING_PUBLIC_SLOTS, "Remaining public slots", DataStructures::Table::NUMERIC},
{DefaultRoomColumns::TC_REMAINING_RESERVED_SLOTS, "Remaining reserved slots", DataStructures::Table::NUMERIC},
{DefaultRoomColumns::TC_REMAINING_SPECTATOR_SLOTS, "Remaining spectator slots", DataStructures::Table::NUMERIC},
{DefaultRoomColumns::TC_CREATION_TIME, "Creation time", DataStructures::Table::NUMERIC},
{DefaultRoomColumns::TC_DESTROY_ON_MODERATOR_LEAVE, "Destroy on moderator leave", DataStructures::Table::NUMERIC},
{DefaultRoomColumns::TC_LOBBY_ROOM_PTR, "Lobby room ptr [Internal]", DataStructures::Table::POINTER},
};
const char *DefaultRoomColumns::GetColumnName(int columnId) {return defaultRoomColumns[columnId].columnName;}
DataStructures::Table::ColumnType DefaultRoomColumns::GetColumnType(int columnId) {return defaultRoomColumns[columnId].columnType;}
bool DefaultRoomColumns::HasColumnName(const char *columnName)
{
unsigned i;
for (i=0; i < TC_TABLE_COLUMNS_COUNT; i++)
if (strcmp(columnName,GetColumnName(i))==0)
return true;
return false;
}
int DefaultRoomColumns::GetColumnIndex(const char *columnName)
{
unsigned i;
for (i=0; i < TC_TABLE_COLUMNS_COUNT; i++)
if (strcmp(columnName,GetColumnName(i))==0)
return i;
return -1;
}
void DefaultRoomColumns::AddDefaultColumnsToTable(DataStructures::Table *table)
{
unsigned i;
for (i=0; i < DefaultRoomColumns::TC_TABLE_COLUMNS_COUNT; i++)
table->AddColumn(DefaultRoomColumns::GetColumnName(i), DefaultRoomColumns::GetColumnType(i));
}
bool DefaultRoomColumns::HasDefaultColumns(DataStructures::Table *table)
{
unsigned i;
for (i=0; i < DefaultRoomColumns::TC_TABLE_COLUMNS_COUNT; i++)
{
if (table->ColumnIndex(DefaultRoomColumns::GetColumnName(i))!=-1)
return true;
}
return false;
}

View File

@ -0,0 +1,86 @@
/*
* Copyright (c) 2014, Oculus VR, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* RakNet License.txt file in the licenses directory of this source tree. An additional grant
* of patent rights can be found in the RakNet Patents.txt file in the same directory.
*
* Modified work: Copyright (c) 2017, SLikeSoft UG (haftungsbeschränkt)
*
* This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
* license found in the license.txt file in the root directory of this source tree.
*/
#include "slikenet/DS_Table.h"
#ifndef __ROOM_TYPES_H
#define __ROOM_TYPES_H
enum RoomMemberMode
{
/// The owner of the room, who is also a player in the room. The owner cannot be a spectator
RMM_MODERATOR,
/// The room member is a player in a public slot
RMM_PUBLIC,
/// The room member is a player in a reserved slot
RMM_RESERVED,
/// The room member is a spectator in a public slot.
RMM_SPECTATOR_PUBLIC,
/// The room member is a spectator in a reserved slot.
RMM_SPECTATOR_RESERVED,
/// Used as a query flag - join any slot that is playable (reserved or public)
RMM_ANY_PLAYABLE,
/// Used as a query flag - join any slot that is for a spectator (reserved or public)
RMM_ANY_SPECTATOR,
};
const char *RoomMemberModeToEnum(RoomMemberMode e);
struct DefaultRoomColumns
{
enum
{
TC_TITLE_NAME,
TC_TITLE_ID,
TC_ROOM_NAME,
TC_ROOM_ID,
TC_TOTAL_SLOTS,
TC_TOTAL_PUBLIC_PLUS_RESERVED_SLOTS,
TC_USED_SLOTS,
TC_USED_PUBLIC_PLUS_RESERVED_SLOTS,
TC_REMAINING_SLOTS,
TC_REMAINING_PUBLIC_PLUS_RESERVED_SLOTS,
TC_TOTAL_PUBLIC_SLOTS,
TC_TOTAL_RESERVED_SLOTS,
TC_TOTAL_SPECTATOR_SLOTS,
TC_USED_PUBLIC_SLOTS,
TC_USED_RESERVED_SLOTS,
TC_USED_SPECTATOR_SLOTS,
TC_REMAINING_PUBLIC_SLOTS,
TC_REMAINING_RESERVED_SLOTS,
TC_REMAINING_SPECTATOR_SLOTS,
TC_CREATION_TIME,
TC_DESTROY_ON_MODERATOR_LEAVE,
TC_LOBBY_ROOM_PTR,
TC_TABLE_COLUMNS_COUNT
} columnId;
const char *columnName;
DataStructures::Table::ColumnType columnType;
static const char *GetColumnName(int columnId);
static int GetColumnIndex(const char *columnName);
static DataStructures::Table::ColumnType GetColumnType(int columnId);
static bool HasColumnName(const char *columnName);
static void AddDefaultColumnsToTable(DataStructures::Table *table);
static bool HasDefaultColumns(DataStructures::Table *table);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,635 @@
/*
* Original work: Copyright (c) 2014, Oculus VR, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* RakNet License.txt file in the licenses directory of this source tree. An additional grant
* of patent rights can be found in the RakNet Patents.txt file in the same directory.
*
*
* Modified work: Copyright (c) 2017, SLikeSoft UG (haftungsbeschränkt)
*
* This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
* license found in the license.txt file in the root directory of this source tree.
*/
#ifndef __LOBBY_ROOM_H
#define __LOBBY_ROOM_H
#include "slikenet/DS_Map.h"
#include "slikenet/DS_Table.h"
#include "RoomsErrorCodes.h"
#include "slikenet/DS_List.h"
#include "slikenet/types.h"
#include "IntervalTimer.h"
#include "RoomTypes.h"
namespace SLNet
{
class ProfanityFilter;
class Room;
class PerGameRoomList;
class PerGameRoomsContainer;
class BitStream;
typedef unsigned int RoomID;
struct QuickJoinUser;
struct RoomMember;
class AllGamesRoomsContainer;
class RoomsParticipant
{
public:
RoomsParticipant() {room=0; inQuickJoin=false;}
~RoomsParticipant() {}
Room * GetRoom(void) const {return room;}
void SetPerGameRoomsContainer(PerGameRoomsContainer *p) {perGameRoomsContainer=p;}
void SetRoom(Room *_room) {room=_room; inQuickJoin=false;}
void SetInQuickJoin(bool b) {inQuickJoin=b; if (b) room=0;}
// 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
SLNet::RakString GetName(void) const {return name;}
void SetName(const char *str) {name = str;}
void SetSystemAddress(const SystemAddress &sa) {systemAddress=sa;}
SystemAddress GetSystemAddress(void) const {return systemAddress;}
void SetGUID(RakNetGUID g) {guid=g;}
RakNetGUID GetGUID(void) const {return guid;}
PerGameRoomsContainer *GetPerGameRoomsContainer(void) const {return perGameRoomsContainer;}
bool GetInQuickJoin(void) const {return inQuickJoin;}
protected:
SLNet::RakString name;
SystemAddress systemAddress;
RakNetGUID guid;
Room *room;
bool inQuickJoin;
PerGameRoomsContainer *perGameRoomsContainer;
};
typedef SLNet::RakString GameIdentifier;
enum RoomLockState
{
// Anyone can join or leave
RLS_NOT_LOCKED,
// Anyone can join as spectator or become spectator. New players are not allowed. You cannot leave spectator.
RLS_PLAYERS_LOCKED,
// No new players are allowed, and you cannot toggle spectator
RLS_ALL_LOCKED
};
enum ParticipantCanJoinRoomResult
{
PCJRR_SUCCESS,
PCJRR_BANNED,
PCJRR_NO_PUBLIC_SLOTS,
PCJRR_NO_PUBLIC_OR_RESERVED_SLOTS,
PCJRR_NO_SPECTATOR_SLOTS,
PCJRR_LOCKED,
PCJRR_SLOT_ALREADY_USED,
};
struct Slots
{
Slots();
~Slots();
unsigned int publicSlots;
unsigned int reservedSlots;
unsigned int spectatorSlots;
unsigned int GetTotalSlots(void) const {return publicSlots+reservedSlots+spectatorSlots;}
void Serialize(bool writeToBitstream, SLNet::BitStream *bitStream);
RoomsErrorCode Validate(void) const;
};
struct InvitedUser
{
InvitedUser() {room=0; roomId=0; invitedAsSpectator=false;}
Room *room;
RoomID roomId;
SLNet::RakString invitorName;
SystemAddress invitorSystemAddress;
SLNet::RakString target;
SLNet::RakString subject;
SLNet::RakString body;
bool invitedAsSpectator;
void Serialize(bool writeToBitstream, SLNet::BitStream *bitStream);
};
struct BannedUser
{
SLNet::RakString target;
SLNet::RakString reason;
void Serialize(bool writeToBitstream, SLNet::BitStream *bitStream);
};
struct RemoveUserResult
{
RemoveUserResult();
~RemoveUserResult();
// Why return a deleted pointer?
// RoomsParticipant *removedUser;
bool removedFromQuickJoin;
bool removedFromRoom;
SystemAddress removedUserAddress;
SLNet::RakString removedUserName;
// Following members only apply if removedFromRoom==true
Room *room;
RoomID roomId;
bool gotNewModerator; // If you were the moderator before, this is true
DataStructures::List<InvitedUser> clearedInvitations; // If invitations were cleared when you leave, these are the invitations
bool roomDestroyed; // Up to caller to deallocate
QuickJoinUser *qju;
void Serialize(bool writeToBitstream, SLNet::BitStream *bitStream);
};
struct RoomMemberDescriptor
{
SLNet::RakString name;
RoomMemberMode roomMemberMode;
bool isReady;
// Filled externally
SystemAddress systemAddress;
RakNetGUID guid;
void FromRoomMember(RoomMember *roomMember);
void Serialize(bool writeToBitstream, SLNet::BitStream *bitStream);
};
struct NetworkedRoomCreationParameters
{
NetworkedRoomCreationParameters() {hiddenFromSearches=false; destroyOnModeratorLeave=false; autoLockReadyStatus=false; inviteToRoomPermission=INVITE_MODE_ANYONE_CAN_INVITE; inviteToSpectatorSlotPermission=INVITE_MODE_ANYONE_CAN_INVITE; clearInvitesOnNewModerator=false;}
// Checked by Validate
Slots slots;
bool hiddenFromSearches;
bool destroyOnModeratorLeave;
bool autoLockReadyStatus; // When everyone is ready and (the room is full or the room is locked), don't allow users to set unready.
enum SendInvitePermission
{
INVITE_MODE_ANYONE_CAN_INVITE,
INVITE_MODE_MODERATOR_CAN_INVITE,
INVITE_MODE_PUBLIC_SLOTS_CAN_INVITE,
INVITE_MODE_RESERVED_SLOTS_CAN_INVITE,
INVITE_MODE_SPECTATOR_SLOTS_CAN_INVITE,
INVITE_MODE_MODERATOR_OR_PUBLIC_SLOTS_CAN_INVITE,
INVITE_MODE_MODERATOR_OR_PUBLIC_OR_RESERVED_SLOTS_CAN_INVITE,
} inviteToRoomPermission, inviteToSpectatorSlotPermission;
bool clearInvitesOnNewModerator; // Leave or change
SLNet::RakString roomName;
void Serialize(bool writeToBitstream, SLNet::BitStream *bitStream);
static const char *SendInvitePermissionToEnum(SendInvitePermission e);
};
struct RoomDescriptor
{
DataStructures::List<RoomMemberDescriptor> roomMemberList;
DataStructures::List<BannedUser> banList;
RoomLockState roomLockState;
RoomID lobbyRoomId;
bool autoLockReadyStatus;
bool hiddenFromSearches;
NetworkedRoomCreationParameters::SendInvitePermission inviteToRoomPermission;
NetworkedRoomCreationParameters::SendInvitePermission inviteToSpectatorSlotPermission;
DataStructures::Table roomProperties;
DataStructures::Table::Cell *GetProperty(const char* columnName)
{
return roomProperties.GetRowByIndex(0,0)->cells[roomProperties.ColumnIndex(columnName)];
}
DataStructures::Table::Cell *GetProperty(int index)
{
return roomProperties.GetRowByIndex(0,0)->cells[index];
}
void Clear(void)
{
roomMemberList.Clear(false, _FILE_AND_LINE_);
banList.Clear(false, _FILE_AND_LINE_);
roomProperties.Clear();
}
void FromRoom(Room *room, AllGamesRoomsContainer *agrc);
void Serialize(bool writeToBitstream, SLNet::BitStream *bitStream);
};
struct JoinedRoomResult
{
JoinedRoomResult() {roomOutput=0; acceptedInvitor=0; agrc=0; joiningMember=0;}
~JoinedRoomResult() {}
Room* roomOutput;
RoomDescriptor roomDescriptor;
RoomsParticipant* acceptedInvitor;
SLNet::RakString acceptedInvitorName;
SystemAddress acceptedInvitorAddress;
RoomsParticipant* joiningMember;
SLNet::RakString joiningMemberName;
SystemAddress joiningMemberAddress;
RakNetGUID joiningMemberGuid;
// Needed to serialize
AllGamesRoomsContainer *agrc;
void Serialize(bool writeToBitstream, SLNet::BitStream *bitStream );
};
struct RoomCreationParameters
{
RoomCreationParameters();
~RoomCreationParameters();
NetworkedRoomCreationParameters networkedRoomCreationParameters;
// Not checked
RoomsParticipant* firstUser;
GameIdentifier gameIdentifier;
// Output parameters:
// Was the room created?
bool createdRoom;
Room *roomOutput;
// May return REC_ROOM_CREATION_PARAMETERS_* or REC_SUCCESS
RoomsErrorCode Validate(
const DataStructures::List<SLNet::RakString> &otherRoomNames,
ProfanityFilter *profanityFilter) const;
};
struct RoomMember
{
RoomMember();
~RoomMember();
RoomsParticipant* roomsParticipant;
RoomMemberMode roomMemberMode;
SLNet::TimeMS joinTime;
bool isReady;
// 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
bool newMemberNotificationProcessed;
};
struct KickedUser
{
RoomsParticipant* roomsParticipant;
SLNet::RakString reason;
};
struct RoomQuery
{
RoomQuery();
~RoomQuery();
// 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)
DataStructures::Table::FilterQuery *queries;
// Size of the queries array
unsigned int numQueries;
// Not used
bool queriesAllocated;
// Helper functions
// Easier to use, but not threadsafe
void AddQuery_NUMERIC(const char *columnName, double numericValue, DataStructures::Table::FilterQueryType op=DataStructures::Table::QF_EQUAL);
void AddQuery_STRING(const char *columnName, const char *charValue, DataStructures::Table::FilterQueryType op=DataStructures::Table::QF_EQUAL);
void AddQuery_BINARY(const char *columnName, const char *input, int inputLength, DataStructures::Table::FilterQueryType op=DataStructures::Table::QF_EQUAL);
void AddQuery_POINTER(const char *columnName, void *ptr, DataStructures::Table::FilterQueryType op=DataStructures::Table::QF_EQUAL);
RoomsErrorCode Validate(void);
void Serialize(bool writeToBitstream, SLNet::BitStream *bitStream);
/// \internal
void SetQueriesToStatic(void);
private:
static DataStructures::Table::FilterQuery fq[32];
static DataStructures::Table::Cell cells[32];
void SetupNextQuery(const char *columnName,DataStructures::Table::FilterQueryType op);
};
struct NetworkedQuickJoinUser
{
NetworkedQuickJoinUser() {timeout=60000; minimumPlayers=2;}
// How long to wait for
SLNet::TimeMS timeout;
// What queries to join the room on.
RoomQuery query;
// Minimum number of slots to join
int minimumPlayers;
void Serialize(bool writeToBitstream, SLNet::BitStream *bitStream);
};
struct QuickJoinUser
{
QuickJoinUser();
~QuickJoinUser();
NetworkedQuickJoinUser networkedQuickJoinUser;
// Total amount of time spent waiting
SLNet::TimeMS totalTimeWaiting;
// Which user
RoomsParticipant* roomsParticipant;
static int SortByTotalTimeWaiting( QuickJoinUser* const &key, QuickJoinUser* const &data );
static int SortByMinimumSlots( QuickJoinUser* const &key, QuickJoinUser* const &data );
};
int RoomPriorityComp( Room * const &key, Room * const &data );
// PerGameRoomsContainer, mapped by game id
class AllGamesRoomsContainer
{
public:
AllGamesRoomsContainer();
~AllGamesRoomsContainer();
static void UnitTest(void);
RoomsErrorCode CreateRoom(RoomCreationParameters *roomCreationParameters,
ProfanityFilter *profanityFilter);
// Enters a room based on the search queries. If no rooms are available to join, will create a room instead
RoomsErrorCode EnterRoom(RoomCreationParameters *roomCreationParameters,
RoomMemberMode roomMemberMode,
ProfanityFilter *profanityFilter,
RoomQuery *query,
JoinedRoomResult *joinRoomResult);
// Attempts to join a room by search query filters
// Returns REC_JOIN_BY_FILTER_*
RoomsErrorCode JoinByFilter(GameIdentifier gameIdentifier, RoomMemberMode roomMemberMode, RoomsParticipant* roomsParticipant, RoomID lastRoomJoined, RoomQuery *query, JoinedRoomResult *joinRoomResult);
// Add a new title to host games with
RoomsErrorCode AddTitle(GameIdentifier gameIdentifier);
// Get all pending invites to you
RoomsErrorCode GetInvitesToParticipant(RoomsParticipant* roomsParticipant, DataStructures::List<InvitedUser*> &invites);
RoomsErrorCode RemoveUser(RoomsParticipant* roomsParticipant, RemoveUserResult *removeMemberResult);
// ROOMS OPERATIONS, implicit room
RoomsErrorCode SendInvite(RoomsParticipant* roomsParticipant, RoomsParticipant* inviteeId, bool inviteToSpectatorSlot, SLNet::RakString subject, SLNet::RakString body);
RoomsErrorCode AcceptInvite(RoomID roomId, Room **room, RoomsParticipant* roomsParticipant, SLNet::RakString inviteSender);
RoomsErrorCode StartSpectating(RoomsParticipant* roomsParticipant);
RoomsErrorCode StopSpectating(RoomsParticipant* roomsParticipant);
RoomsErrorCode GrantModerator(RoomsParticipant* roomsParticipant, RoomsParticipant *newModerator, DataStructures::List<InvitedUser> &clearedInvites);
RoomsErrorCode ChangeSlotCounts(RoomsParticipant* roomsParticipant, Slots slots);
RoomsErrorCode SetCustomRoomProperties(RoomsParticipant* roomsParticipant, DataStructures::Table *table);
RoomsErrorCode ChangeRoomName(RoomsParticipant* roomsParticipant, SLNet::RakString newRoomName, ProfanityFilter *profanityFilter);
RoomsErrorCode SetHiddenFromSearches(RoomsParticipant* roomsParticipant, bool _hiddenFromSearches);
RoomsErrorCode SetDestroyOnModeratorLeave(RoomsParticipant* roomsParticipant, bool destroyOnModeratorLeave);
RoomsErrorCode SetReadyStatus(RoomsParticipant* roomsParticipant, bool isReady);
RoomsErrorCode GetReadyStatus( RoomID roomId, Room **room, DataStructures::List<RoomsParticipant*> &readyUsers, DataStructures::List<RoomsParticipant*> &unreadyUsers);
RoomsErrorCode SetRoomLockState(RoomsParticipant* roomsParticipant, RoomLockState _roomLockState);
RoomsErrorCode GetRoomLockState(RoomID roomId, Room **room, RoomLockState *roomLockState);
RoomsErrorCode AreAllMembersReady(RoomID roomId, Room **room, bool *allReady);
RoomsErrorCode KickMember(RoomsParticipant* roomsParticipant, RoomsParticipant *kickedParticipant, SLNet::RakString reason);
RoomsErrorCode UnbanMember(RoomsParticipant* roomsParticipant, SLNet::RakString name);
RoomsErrorCode GetBanReason( RoomID lobbyRoomId, Room **room, SLNet::RakString name, SLNet::RakString *reason);
RoomsErrorCode LeaveRoom(RoomsParticipant* roomsParticipant, RemoveUserResult *removeUserResult);
//RoomsErrorCode GetKickReason(RoomsParticipant* roomsParticipant, SLNet::RakString *kickReason);
void GetRoomProperties(RoomID roomId, Room **room, DataStructures::Table *table);
// Quick join algorithm:
//
// -- ROOM JOIN --
//
// For all rooms:
// 1. Clear all quickJoinWorkingList from all rooms
// For all quick join members
// 2. Use RoomPrioritySort to get all rooms they can potentially join
// 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
// For all rooms:
// 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.
//
// -- ROOM CREATE --
//
// 5. Sort quick join members by minimumPlayers, excluding members where minimumPlayers > total number of quick join members
// From greatest minimumPlayers to least
// 6. If the current member created a room, find out how many subsequent members would join based on the custom filter
// 7. If this satisfies minimumPlayers, have that user create a room and those subsequent members join.
//
// -- EXPIRE
//
// 5. Remove from list if timeout has expired.
// 6. Return results of operation (List<timeoutExpired>, List<joinedARoom>, List<RoomsThatWereJoined>
//
// Returns false if processing skipped due to optimization timer
RoomsErrorCode ProcessQuickJoins(
DataStructures::List<QuickJoinUser*> &timeoutExpired,
DataStructures::List<JoinedRoomResult> &joinedRoomMembers,
DataStructures::List<QuickJoinUser*> &dereferencedPointers,
SLNet::TimeMS elapsedTime);
// Quick join - Store a list of all members waiting to quick join.
// Quick join ends when
// 1. An existing room can be fully populated using waiting quick join members.
// 2. Enough quick join members are waiting that a new room can be created with the number of members >= minimumPlayers for all members
// It also ends if timeToWaitMS expires.
// Returns REC_ADD_TO_QUICK_JOIN_*
// Passed pointer is stored on REC_SUCCESS, allocate, and do not deallocate unless not successful
RoomsErrorCode AddUserToQuickJoin(GameIdentifier gameIdentifier, QuickJoinUser *quickJoinMember);
// Returns REC_REMOVE_FROM_QUICK_JOIN_*
RoomsErrorCode RemoveUserFromQuickJoin(RoomsParticipant* roomsParticipant, QuickJoinUser **qju);
// Is this user in quick join?
bool IsInQuickJoin(RoomsParticipant* roomsParticipant);
// Get all rooms for a certain title
static int RoomsSortByName( Room* const &key, Room* const &data );
RoomsErrorCode SearchByFilter( GameIdentifier gameIdentifier, RoomsParticipant* roomsParticipant, RoomQuery *roomQuery, DataStructures::OrderedList<Room*, Room*, RoomsSortByName> &roomsOutput, bool onlyJoinable );
// Deallocate a room
void DestroyRoomIfDead(Room *room);
// If a handle changes, you have to tell the system here. Otherwise ban and invite names will be out of synch
// System does not verify that the handle is not currently in use since it does not necessarily know about all online players
// This is an invariant up to the caller to uphold. Failure to do so will result in the wrong players being banned or invited
void ChangeHandle(SLNet::RakString oldHandle, SLNet::RakString newHandle);
unsigned int GetPropertyIndex(RoomID lobbyRoomId, const char *propertyName) const;
DataStructures::Map<GameIdentifier, PerGameRoomsContainer*> perGamesRoomsContainers;
Room * GetRoomByLobbyRoomID(RoomID lobbyRoomID);
Room * GetRoomByName(SLNet::RakString roomName);
protected:
RoomID nextRoomId;
};
class PerGameRoomsContainer
{
public:
PerGameRoomsContainer();
~PerGameRoomsContainer();
// Has pointer column to class Room
DataStructures::Table roomsTable;
// Members that are waiting to quick join
DataStructures::List<QuickJoinUser*> quickJoinList;
static int RoomsSortByTimeThenTotalSlots( Room* const &key, Room* const &data );
protected:
RoomsErrorCode CreateRoom(RoomCreationParameters *roomCreationParameters,
ProfanityFilter *profanityFilter,
RoomID lobbyRoomId,
bool validate);
RoomsErrorCode LeaveRoom(RoomsParticipant* roomsParticipant, bool *gotNewModerator);
RoomsErrorCode JoinByFilter(RoomMemberMode roomMemberMode, RoomsParticipant* roomsParticipant, RoomID lastRoomJoined, RoomQuery *query, JoinedRoomResult *joinRoomResult);
RoomsErrorCode AddUserToQuickJoin(QuickJoinUser *quickJoinMember);
RoomsErrorCode RemoveUserFromQuickJoin(RoomsParticipant* roomsParticipant, QuickJoinUser **qju);
bool IsInQuickJoin(RoomsParticipant* roomsParticipant);
unsigned int GetQuickJoinIndex(RoomsParticipant* roomsParticipant);
void GetRoomNames(DataStructures::List<SLNet::RakString> &roomNames);
void GetAllRooms(DataStructures::List<Room*> &rooms);
// Looks for a particular room that has a particular ID
Room * GetRoomByLobbyRoomID(RoomID lobbyRoomID);
Room * GetRoomByName(SLNet::RakString roomName);
RoomsErrorCode GetInvitesToParticipant(RoomsParticipant* roomsParticipant, DataStructures::List<InvitedUser*> &invites);
bool DestroyRoomIfDead(Room *room);
void ChangeHandle(SLNet::RakString oldHandle, SLNet::RakString newHandle);
unsigned ProcessQuickJoins( DataStructures::List<QuickJoinUser*> &timeoutExpired,
DataStructures::List<JoinedRoomResult> &joinedRooms,
DataStructures::List<QuickJoinUser*> &dereferencedPointers,
SLNet::TimeMS elapsedTime,
RoomID startingRoomId);
// Sort an input list of rooms
// 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).
// When using EnterRoom or JoinByFilter, record the last roomOutput joined, and try to avoid rejoining the same roomOutput just left
void RoomPrioritySort( RoomsParticipant* roomsParticipant, RoomQuery *roomQuery, DataStructures::OrderedList<Room*, Room*, RoomsSortByTimeThenTotalSlots> &roomsOutput );
RoomsErrorCode SearchByFilter( RoomsParticipant* roomsParticipant, RoomQuery *roomQuery, DataStructures::OrderedList<Room*, Room*, AllGamesRoomsContainer::RoomsSortByName> &roomsOutput, bool onlyJoinable );
friend class AllGamesRoomsContainer;
IntervalTimer nextQuickJoinProcess;
};
// Holds all the members of a particular roomOutput
class Room
{
public:
Room( RoomID _roomId, RoomCreationParameters *roomCreationParameters, DataStructures::Table::Row *_row, RoomsParticipant* roomsParticipant );
~Room();
RoomsErrorCode SendInvite(RoomsParticipant* roomsParticipant, RoomsParticipant* inviteeId, bool inviteToSpectatorSlot, SLNet::RakString subject, SLNet::RakString body);
RoomsErrorCode AcceptInvite(RoomsParticipant* roomsParticipant, SLNet::RakString inviteSender);
RoomsErrorCode StartSpectating(RoomsParticipant* roomsParticipant);
RoomsErrorCode StopSpectating(RoomsParticipant* roomsParticipant);
RoomsErrorCode GrantModerator(RoomsParticipant* roomsParticipant, RoomsParticipant *newModerator, DataStructures::List<InvitedUser> &clearedInvites);
RoomsErrorCode ChangeSlotCounts(RoomsParticipant* roomsParticipant, Slots slots);
RoomsErrorCode SetCustomRoomProperties(RoomsParticipant* roomsParticipant, DataStructures::Table *table);
RoomsErrorCode ChangeRoomName(RoomsParticipant* roomsParticipant, SLNet::RakString newRoomName, ProfanityFilter *profanityFilter);
RoomsErrorCode SetHiddenFromSearches(RoomsParticipant* roomsParticipant, bool _hiddenFromSearches);
RoomsErrorCode SetDestroyOnModeratorLeave(RoomsParticipant* roomsParticipant, bool destroyOnModeratorLeave);
RoomsErrorCode SetReadyStatus(RoomsParticipant* roomsParticipant, bool isReady);
RoomsErrorCode GetReadyStatus(DataStructures::List<RoomsParticipant*> &readyUsers, DataStructures::List<RoomsParticipant*> &unreadyUsers);
RoomsErrorCode SetRoomLockState(RoomsParticipant* roomsParticipant, RoomLockState _roomLockState);
RoomsErrorCode GetRoomLockState(RoomLockState *_roomLockState);
RoomsErrorCode AreAllMembersReady(unsigned int exceptThisIndex, bool *allReady);
RoomsErrorCode KickMember(RoomsParticipant* roomsParticipant, RoomsParticipant *kickedParticipant, SLNet::RakString reason);
RoomsErrorCode UnbanMember(RoomsParticipant* roomsParticipant, SLNet::RakString name);
RoomsErrorCode GetBanReason(SLNet::RakString name, SLNet::RakString *reason);
RoomsErrorCode LeaveRoom(RoomsParticipant* roomsParticipant, RemoveUserResult *removeUserResult);
//RoomsErrorCode GetKickReason(RoomsParticipant* roomsParticipant, SLNet::RakString *kickReason);
RoomsErrorCode JoinByFilter(RoomsParticipant* roomsParticipant, RoomMemberMode roomMemberMode, JoinedRoomResult *joinRoomResult);
RoomsErrorCode JoinByQuickJoin(RoomsParticipant* roomsParticipant, RoomMemberMode roomMemberMode, JoinedRoomResult *joinRoomResult);
bool IsHiddenToParticipant(RoomsParticipant* roomsParticipant) const;
// Can this user join this roomOutput?
ParticipantCanJoinRoomResult ParticipantCanJoinAsPlayer( RoomsParticipant* roomsParticipant, bool asSpectator, bool checkHasInvite );
ParticipantCanJoinRoomResult ParticipantCanJoinRoom( RoomsParticipant* roomsParticipant, bool asSpectator, bool checkHasInvite );
// Returns true if there are only spectators, or nobody at all
bool IsRoomDead(void) const;
RoomsErrorCode GetInvitesToParticipant(RoomsParticipant* roomsParticipant, DataStructures::List<InvitedUser*> &invites);
RoomsParticipant* GetModerator(void) const;
// Gets the roomOutput ID
RoomID GetID(void) const;
double GetNumericProperty(RoomID lobbyRoomId, const char *propertyName) const;
const char *GetStringProperty(RoomID lobbyRoomId, const char *propertyName) const;
double GetNumericProperty(int index) const;
const char *GetStringProperty(int index) const;
void SetNumericProperty(int index, double value);
void SetStringProperty(int index, const char *value);
// Public for easy access
DataStructures::List<RoomMember*> roomMemberList;
DataStructures::List<InvitedUser> inviteList;
DataStructures::List<BannedUser> banList;
// Don't store - slow because when removing users I have to iterate through every room
// DataStructures::List<KickedUser> kickedList;
// Internal
DataStructures::List<QuickJoinUser*> quickJoinWorkingList;
static void UpdateRowSlots( DataStructures::Table::Row* row, Slots *totalSlots, Slots *usedSlots);
void ChangeHandle(SLNet::RakString oldHandle, SLNet::RakString newHandle);
protected:
Room();
// Updates the table row
RoomsErrorCode RemoveUser(RoomsParticipant* roomsParticipant,RemoveUserResult *removeUserResult);
bool IsRoomLockedToSpectators(void) const;
bool IsRoomLockedToPlayers(void) const;
bool IsInRoom(RoomsParticipant* roomsParticipant) const;
bool HasInvite(SLNet::RakString roomsParticipant);
unsigned int GetRoomIndex(RoomsParticipant* roomsParticipant) const;
unsigned int GetBannedIndex(SLNet::RakString username) const;
unsigned int GetInviteIndex(SLNet::RakString invitee, SLNet::RakString invitor) const;
unsigned int GetFirstInviteIndex(SLNet::RakString invitee) const;
bool AreAllPlayableSlotsFilled(void) const;
bool HasOpenPublicSlots(void) const;
bool HasOpenReservedSlots(void) const;
bool HasOpenSpectatorSlots(void) const;
void UpdateUsedSlots( void );
void UpdateUsedSlots( Slots *totalSlots, Slots *usedSlots );
static void UpdateUsedSlots( DataStructures::Table::Row* tableRow, Slots *totalSlots, Slots *usedSlots );
Slots GetTotalSlots(void) const;
void SetTotalSlots(Slots *totalSlots);
Slots GetUsedSlots(void) const;
RoomLockState roomLockState;
friend struct RoomDescriptor;
friend class PerGameRoomsContainer;
friend class AllGamesRoomsContainer;
RoomID lobbyRoomId;
DataStructures::Table::Row *tableRow;
bool autoLockReadyStatus;
bool hiddenFromSearches;
// bool destroyOnModeratorLeave;
bool clearInvitesOnNewModerator;
NetworkedRoomCreationParameters::SendInvitePermission inviteToRoomPermission, inviteToSpectatorSlotPermission;
bool roomDestroyed;
};
} // namespace Lobby2
#endif

View File

@ -0,0 +1,194 @@
/*
* Original work: Copyright (c) 2014, Oculus VR, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* RakNet License.txt file in the licenses directory of this source tree. An additional grant
* of patent rights can be found in the RakNet Patents.txt file in the same directory.
*
*
* Modified work: Copyright (c) 2017-2019, SLikeSoft UG (haftungsbeschränkt)
*
* This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
* license found in the license.txt file in the root directory of this source tree.
*/
#include "RoomsErrorCodes.h"
#include "slikenet/assert.h"
using namespace SLNet;
static RoomsErrorCodeDescription errorCodeDescriptions[ROOMS_ERROR_CODES_COUNT] =
{
{REC_SUCCESS, "REC_SUCCESS", "Success."},
{REC_USERNAME_IS_EMPTY, "REC_USERNAME_IS_EMPTY", "Username is empty."},
{REC_NOT_LOGGED_IN, "REC_NOT_LOGGED_IN", "Not logged in."},
{REC_ADD_TO_ROOM_NO_RESERVED_OR_PUBLIC, "REC_ADD_TO_ROOM_NO_RESERVED_OR_PUBLIC", "Failed to enter the room. Room has no reserved or public slots available to join."},
{REC_ADD_TO_ROOM_NO_PUBLIC, "REC_ADD_TO_ROOM_NO_PUBLIC", "Failed to enter the room. Room has no public slots available to join."},
{REC_ADD_TO_ROOM_NO_SPECTATOR, "REC_ADD_TO_ROOM_NO_SPECTATOR", "Failed to enter the room. Room has no spectator slots available to join."},
{REC_ADD_TO_ROOM_ALREADY_IN_THIS_ROOM, "REC_ADD_TO_ROOM_ALREADY_IN_THIS_ROOM", "Failed to enter the room. You are already in this room."},
{REC_ADD_TO_ROOM_ALREADY_IN_ANOTHER_ROOM, "REC_ADD_TO_ROOM_ALREADY_IN_ANOTHER_ROOM", "Failed to enter the room. You are already in a different room. Leave your existing room first."},
{REC_ADD_TO_ROOM_KICKED_OUT_OF_ROOM, "REC_ADD_TO_ROOM_KICKED_OUT_OF_ROOM", "Failed to enter the room. You have been banned from this room."},
{REC_CHANGE_MEMBER_TYPE_NO_SLOTS, "REC_CHANGE_MEMBER_TYPE_NO_SLOTS", "The room does not have free slots of the desired type."},
{REC_SEARCH_BY_FILTER_UNKNOWN_TITLE, "REC_SEARCH_BY_FILTER_UNKNOWN_TITLE", "Unknown title (Programmer error)."},
{REC_JOIN_BY_FILTER_UNKNOWN_TITLE, "REC_JOIN_BY_FILTER_UNKNOWN_TITLE", "Room join failed. Unknown title (Programmer error)."},
{REC_JOIN_BY_FILTER_NO_ROOMS, "REC_JOIN_BY_FILTER_NO_ROOMS", "Room join failed. There are no rooms, or no rooms that meet your search requirements."},
{REC_JOIN_BY_FILTER_CURRENTLY_IN_A_ROOM, "REC_JOIN_BY_FILTER_CURRENTLY_IN_A_ROOM", "Room join failed. You are already in a room."},
{REC_JOIN_BY_FILTER_CURRENTLY_IN_QUICK_JOIN, "REC_JOIN_BY_FILTER_CURRENTLY_IN_QUICK_JOIN", "Room join failed. You are currently in quick join. Leave quick join first."},
{REC_JOIN_BY_FILTER_CANNOT_JOIN_AS_MODERATOR, "REC_JOIN_BY_FILTER_CANNOT_JOIN_AS_MODERATOR", "Room join failed. You cannot join an existing room as a moderator. Create a new room instead."},
{REC_JOIN_BY_FILTER_ROOM_LOCKED, "REC_JOIN_BY_FILTER_ROOM_LOCKED", "Room join failed. The room is locked to new players."},
{REC_JOIN_BY_FILTER_BANNED, "REC_JOIN_BY_FILTER_BANNED", "Room join failed. You are banned from this room."},
{REC_JOIN_BY_FILTER_NO_SLOTS, "REC_JOIN_BY_FILTER_NO_SLOTS", "Room join failed. The room is full."},
{REC_JOIN_BY_QUICK_JOIN_CANNOT_JOIN_AS_MODERATOR, "REC_JOIN_BY_QUICK_JOIN_CANNOT_JOIN_AS_MODERATOR", "Quick join failed. You cannot join an existing room as a moderator. Create a new room instead."},
{REC_JOIN_BY_QUICK_JOIN_ROOM_LOCKED, "REC_JOIN_BY_QUICK_JOIN_ROOM_LOCKED", "Quick join failed. All rooms are locked to new players."},
{REC_JOIN_BY_QUICK_JOIN_BANNED, "REC_JOIN_BY_QUICK_JOIN_BANNED", "Quick join failed. You are banned from the only available rooms."},
{REC_JOIN_BY_QUICK_JOIN_NO_SLOTS, "REC_JOIN_BY_QUICK_JOIN_NO_SLOTS", "Quick join failed. All rooms are full."},
{REC_ADD_TO_QUICK_JOIN_CURRENTLY_IN_A_ROOM, "REC_ADD_TO_QUICK_JOIN_CURRENTLY_IN_A_ROOM", "Failed to quick join. You are currently in a room. Leave your existing room first."},
{REC_ADD_TO_QUICK_JOIN_UNKNOWN_TITLE, "REC_ADD_TO_QUICK_JOIN_UNKNOWN_TITLE", "Failed to quick join. Unknown title (Programmer error)."},
{REC_ADD_TO_QUICK_JOIN_ALREADY_THERE, "REC_ADD_TO_QUICK_JOIN_ALREADY_THERE", "Quick join is already in progress."},
{REC_ADD_TO_QUICK_JOIN_INVALID_TIMEOUT_TOO_LOW, "REC_ADD_TO_QUICK_JOIN_INVALID_TIMEOUT_TOO_LOW", "Failed to quick join. Tiebout is below the minimum threshold."},
{REC_ADD_TO_QUICK_JOIN_INVALID_TIMEOUT_TOO_HIGH, "REC_ADD_TO_QUICK_JOIN_INVALID_TIMEOUT_TOO_HIGH", "Failed to quick join. Timeout is above the minimum threshold."},
{REC_ADD_TO_QUICK_JOIN_MINIMUM_SLOTS_TOO_LOW, "REC_ADD_TO_QUICK_JOIN_MINIMUM_SLOTS_TOO_LOW", "Failed to quick join. Must have at least one slot for other players."},
{REC_ADD_TO_QUICK_JOIN_MINIMUM_SLOTS_TOO_HIGH, "REC_ADD_TO_QUICK_JOIN_MINIMUM_SLOTS_TOO_HIGH", "Failed to quick join. Too many player slots."},
{REC_REMOVE_FROM_QUICK_UNKNOWN_TITLE, "REC_REMOVE_FROM_QUICK_UNKNOWN_TITLE", "Failed to leave quick join. Unknown title (Programmer error)."},
{REC_REMOVE_FROM_QUICK_JOIN_NOT_THERE, "REC_REMOVE_FROM_QUICK_JOIN_NOT_THERE", "Failed to leave quick join. You are not in quick join to begin with."},
{REC_CREATE_ROOM_UNKNOWN_TITLE, "REC_CREATE_ROOM_UNKNOWN_TITLE", "Failed to create a room. Unknown title (Programmer error)."},
{REC_CREATE_ROOM_CURRENTLY_IN_QUICK_JOIN, "REC_CREATE_ROOM_CURRENTLY_IN_QUICK_JOIN", "Failed to create a room. You are currently in quick join. Leave quick join first."},
{REC_CREATE_ROOM_CURRENTLY_IN_A_ROOM, "REC_CREATE_ROOM_CURRENTLY_IN_A_ROOM", "Failed to create a room. You are already in a room."},
{REC_ROOM_CREATION_PARAMETERS_EMPTY_ROOM_NAME, "REC_ROOM_CREATION_PARAMETERS_EMPTY_ROOM_NAME", "You must specify a room name."},
{REC_ROOM_CREATION_PARAMETERS_RESERVED_QUICK_JOIN_ROOM_NAME, "REC_ROOM_CREATION_PARAMETERS_RESERVED_QUICK_JOIN_ROOM_NAME", "Invalid room creation parameters. The room name is reserved for quick join matches."},
{REC_ROOM_CREATION_PARAMETERS_ROOM_NAME_HAS_PROFANITY, "REC_ROOM_CREATION_PARAMETERS_ROOM_NAME_HAS_PROFANITY", "The desired room name cannot contain profanity."},
{REC_ROOM_CREATION_PARAMETERS_ROOM_NAME_IN_USE, "REC_ROOM_CREATION_PARAMETERS_ROOM_NAME_IN_USE", "The desired room name is already in use."},
{REC_ROOM_CREATION_PARAMETERS_NO_PLAYABLE_SLOTS, "REC_ROOM_CREATION_PARAMETERS_NO_PLAYABLE_SLOTS", "Invalid room creation parameters. The room must have at least one playable slot."},
{REC_SET_ROOM_PROPERTIES_UNKNOWN_ROOM, "REC_SET_ROOM_PROPERTIES_UNKNOWN_ROOM", "Unknown room."},
{REC_LEAVE_ROOM_UNKNOWN_ROOM_ID, "REC_LEAVE_ROOM_UNKNOWN_ROOM_ID", "Failed to leave a room. Your room no longer exists."},
{REC_LEAVE_ROOM_CURRENTLY_IN_QUICK_JOIN, "REC_LEAVE_ROOM_CURRENTLY_IN_QUICK_JOIN", "Failed to leave a room. You are currently in quick join. Leave quick join first."},
{REC_LEAVE_ROOM_NOT_IN_ROOM, "REC_LEAVE_ROOM_NOT_IN_ROOM", "You are not currently in a room."},
{REC_ENTER_ROOM_UNKNOWN_TITLE, "REC_ENTER_ROOM_UNKNOWN_TITLE", "Failed to enter a room. Unknown title (Programmer error)."},
{REC_ENTER_ROOM_CURRENTLY_IN_QUICK_JOIN, "REC_ENTER_ROOM_CURRENTLY_IN_QUICK_JOIN", "Failed to enter a room. You are currently in quick join. Leave quick join first."},
{REC_ENTER_ROOM_CURRENTLY_IN_A_ROOM, "REC_ENTER_ROOM_CURRENTLY_IN_A_ROOM", "Failed to enter a room. You are already in a room."},
{REC_PROCESS_QUICK_JOINS_UNKNOWN_TITLE, "REC_PROCESS_QUICK_JOINS_UNKNOWN_TITLE", "Unknown title (Programmer error)."},
{REC_ROOM_QUERY_TOO_MANY_QUERIES, "REC_ROOM_QUERY_TOO_MANY_QUERIES,", "Failed to process room query. Too many queries."},
{REC_ROOM_QUERY_INVALID_QUERIES_POINTER, "REC_ROOM_QUERY_INVALID_QUERIES_POINTER", "Failed to process room query. Query pointer is null."},
{REC_SEND_INVITE_UNKNOWN_ROOM_ID, "REC_SEND_INVITE_UNKNOWN_ROOM_ID", "Failed to send room invite. Your room no longer exists."},
{REC_SEND_INVITE_INVITEE_ALREADY_INVITED, "REC_SEND_INVITE_INVITEE_ALREADY_INVITED", "User was already invited to the room."},
{REC_SEND_INVITE_CANNOT_PERFORM_ON_SELF, "REC_SEND_INVITE_CANNOT_PERFORM_ON_SELF", "Cannot invite yourself."},
{REC_SEND_INVITE_INVITOR_ONLY_MODERATOR_CAN_INVITE, "REC_SEND_INVITE_INVITOR_ONLY_MODERATOR_CAN_INVITE", "Failed to send room invite. Room settings only allows the moderator to invite."},
{REC_SEND_INVITE_INVITOR_LACK_INVITE_PERMISSIONS, "REC_SEND_INVITE_INVITOR_LACK_INVITE_PERMISSIONS", "Failed to send room invite. Room settings does not allow invites to the desired slot type."},
{REC_SEND_INVITE_INVITOR_NOT_IN_ROOM, "REC_SEND_INVITE_INVITOR_NOT_IN_ROOM", "Failed to send room invite. You are not in the room you are trying to invite to."},
{REC_SEND_INVITE_NO_SLOTS, "REC_SEND_INVITE_NO_SLOTS", "Failed to send room invite. The room is full."},
{REC_SEND_INVITE_INVITEE_ALREADY_IN_THIS_ROOM, "REC_SEND_INVITE_INVITEE_ALREADY_IN_THIS_ROOM", "Failed to send room invite. This member is already in the room."},
{REC_SEND_INVITE_INVITEE_BANNED, "REC_SEND_INVITE_INVITEE_BANNED", "Failed to send room invite. The target member was banned from the room."},
{REC_SEND_INVITE_RECIPIENT_NOT_ONLINE, "REC_SEND_INVITE_RECIPIENT_NOT_ONLINE", "Failed to send room invite. The target member is not online."},
{REC_SEND_INVITE_ROOM_LOCKED, "REC_SEND_INVITE_ROOM_LOCKED", "Failed to send room invite. The room is locked to players of the intended slot."},
{REC_ACCEPT_INVITE_UNKNOWN_ROOM_ID, "REC_ACCEPT_INVITE_UNKNOWN_ROOM_ID", "Failed to accept room invite. Your room no longer exists."},
{REC_ACCEPT_INVITE_CURRENTLY_IN_A_ROOM, "REC_ACCEPT_INVITE_CURRENTLY_IN_A_ROOM", "Failed to accept room invite. You are already in a room. Leave the room first."},
{REC_ACCEPT_INVITE_CURRENTLY_IN_QUICK_JOIN, "REC_ACCEPT_INVITE_CURRENTLY_IN_QUICK_JOIN", "Failed to accept room invite. You are currently in quick join. Leave quick join first."},
{REC_ACCEPT_INVITE_BANNED, "REC_ACCEPT_INVITE_BANNED", "Failed to accept room invite. The moderator has banned you from the room."},
{REC_ACCEPT_INVITE_NO_SLOTS, "REC_ACCEPT_INVITE_NO_SLOTS", "Failed to accept room invite. The room is full for the specified slot type."},
{REC_ACCEPT_INVITE_ROOM_LOCKED, "REC_ACCEPT_INVITE_ROOM_LOCKED", "Failed to accept room invite. The room has been locked to the specified slot type."},
{REC_ACCEPT_INVITE_NO_SUCH_INVITE, "REC_ACCEPT_INVITE_NO_SUCH_INVITE", "Failed to accept room invite. You have no pending invites to this room."},
{REC_SLOTS_VALIDATION_NO_PLAYABLE_SLOTS, "REC_SLOTS_VALIDATION_NO_PLAYABLE_SLOTS", "Invalid room slots. The room must have at least one playable slot."},
{REC_SLOTS_VALIDATION_NEGATIVE_PUBLIC_SLOTS, "REC_SLOTS_VALIDATION_NEGATIVE_PUBLIC_SLOTS", "Invalid room slots. Public slots cannot be negative."},
{REC_SLOTS_VALIDATION_NEGATIVE_RESERVED_SLOTS, "REC_SLOTS_VALIDATION_NEGATIVE_RESERVED_SLOTS", "Invalid room slots. Reserved slots cannot be negative."},
{REC_SLOTS_VALIDATION_NEGATIVE_SPECTATOR_SLOTS, "REC_SLOTS_VALIDATION_NEGATIVE_SPECTATOR_SLOTS", "Invalid room slots. Spectator slots cannot be negative."},
{REC_START_SPECTATING_UNKNOWN_ROOM_ID, "REC_START_SPECTATING_UNKNOWN_ROOM_ID", "Failed to spectate. Your room no longer exists."},
{REC_START_SPECTATING_ALREADY_SPECTATING, "REC_START_SPECTATING_ALREADY_SPECTATING", "You are already spectating."},
{REC_START_SPECTATING_NO_SPECTATOR_SLOTS_AVAILABLE, "REC_START_SPECTATING_NO_SPECTATOR_SLOTS_AVAILABLE", "Failed to spectate. No spectator slots available."},
{REC_START_SPECTATING_NOT_IN_ROOM, "REC_START_SPECTATING_NOT_IN_ROOM", "Failed to spectate. Your room no longer exists."},
{REC_START_SPECTATING_REASSIGN_MODERATOR_BEFORE_SPECTATE, "REC_START_SPECTATING_REASSIGN_MODERATOR_BEFORE_SPECTATE", "The moderator cannot spectate wthout first granting moderator to another player."},
{REC_START_SPECTATING_ROOM_LOCKED, "REC_START_SPECTATING_ROOM_LOCKED", "Failed to spectate. The room has been locked."},
{REC_STOP_SPECTATING_UNKNOWN_ROOM_ID, "REC_STOP_SPECTATING_UNKNOWN_ROOM_ID", "Failed to stop spectating. Your room no longer exists."},
{REC_STOP_SPECTATING_NOT_IN_ROOM, "REC_STOP_SPECTATING_NOT_IN_ROOM", "Failed to stop spectating. You are not in a room."},
{REC_STOP_SPECTATING_NOT_CURRENTLY_SPECTATING, "REC_STOP_SPECTATING_NOT_CURRENTLY_SPECTATING", "Failed to stop spectating. You are not currently spectating."},
{REC_STOP_SPECTATING_NO_SLOTS, "REC_STOP_SPECTATING_NO_SLOTS", "Failed to stop spectating. All player slots are full."},
{REC_STOP_SPECTATING_ROOM_LOCKED, "REC_STOP_SPECTATING_ROOM_LOCKED", "Failed to stop spectating. The room has been locked."},
{REC_GRANT_MODERATOR_UNKNOWN_ROOM_ID, "REC_GRANT_MODERATOR_UNKNOWN_ROOM_ID", "Failed to grant moderator to another player. Your room no longer exists."},
{REC_GRANT_MODERATOR_NEW_MODERATOR_NOT_ONLINE, "REC_GRANT_MODERATOR_NEW_MODERATOR_NOT_ONLINE", "Failed to grant moderator to another player. The new moderator is not online."},
{REC_GRANT_MODERATOR_NOT_IN_ROOM, "REC_GRANT_MODERATOR_NOT_IN_ROOM", "Failed to grant moderator to another player. You are not in a room."},
{REC_GRANT_MODERATOR_NEW_MODERATOR_NOT_IN_ROOM, "REC_GRANT_MODERATOR_NEW_MODERATOR_NOT_IN_ROOM", "Failed to grant moderator to another player. The new moderator is not in the room."},
{REC_GRANT_MODERATOR_CANNOT_PERFORM_ON_SELF, "REC_GRANT_MODERATOR_CANNOT_PERFORM_ON_SELF", "You are already the moderator."},
{REC_GRANT_MODERATOR_MUST_BE_MODERATOR_TO_GRANT_MODERATOR, "REC_GRANT_MODERATOR_MUST_BE_MODERATOR_TO_GRANT_MODERATOR", "Failed to grant moderator to another player. You must be moderator to do this."},
{REC_GRANT_MODERATOR_NEW_MODERATOR_NOT_IN_PLAYABLE_SLOT, "REC_GRANT_MODERATOR_NEW_MODERATOR_NOT_IN_PLAYABLE_SLOT", "Failed to grant moderator to another player. The new moderator must be in a playable slot (not spectating)."},
{REC_CHANGE_SLOT_COUNTS_UNKNOWN_ROOM_ID, "REC_CHANGE_SLOT_COUNTS_UNKNOWN_ROOM_ID", "Failed to change slot counts. Your room no longer exists."},
{REC_CHANGE_SLOT_COUNTS_NOT_IN_ROOM, "REC_CHANGE_SLOT_COUNTS_NOT_IN_ROOM", "Failed to change slot counts. You are not in a room."},
{REC_CHANGE_SLOT_COUNTS_MUST_BE_MODERATOR, "REC_CHANGE_SLOT_COUNTS_MUST_BE_MODERATOR", "Failed to change slot counts. You must be moderator to do this."},
{REC_SET_CUSTOM_ROOM_PROPERTIES_UNKNOWN_ROOM_ID, "REC_SET_CUSTOM_ROOM_PROPERTIES_UNKNOWN_ROOM_ID", "Failed to set room properties. Your room no longer exists."},
{REC_SET_CUSTOM_ROOM_PROPERTIES_CONTAINS_DEFAULT_COLUMNS, "REC_SET_CUSTOM_ROOM_PROPERTIES_CONTAINS_DEFAULT_COLUMNS", "Failed to set custom room properties. Custom properties cannot contain default columns. Use the provided functions for this."},
{REC_SET_CUSTOM_ROOM_PROPERTIES_NOT_IN_ROOM, "REC_SET_CUSTOM_ROOM_PROPERTIES_NOT_IN_ROOM", "Failed to set room properties. You are not in a room."},
{REC_SET_CUSTOM_ROOM_PROPERTIES_MUST_BE_MODERATOR, "REC_SET_CUSTOM_ROOM_PROPERTIES_MUST_BE_MODERATOR", "Failed to set room properties. You must be moderator to do this."},
{REC_GET_ROOM_PROPERTIES_EMPTY_ROOM_NAME_AND_NOT_IN_A_ROOM, "REC_GET_ROOM_PROPERTIES_EMPTY_ROOM_NAME_AND_NOT_IN_A_ROOM", "Failed to get room properties. The room name is empty."},
{REC_GET_ROOM_PROPERTIES_UNKNOWN_ROOM_NAME, "REC_GET_ROOM_PROPERTIES_UNKNOWN_ROOM_NAME", "Failed to get room properties. Named room does not exist."},
{REC_CHANGE_ROOM_NAME_UNKNOWN_ROOM_ID, "REC_CHANGE_ROOM_NAME_UNKNOWN_ROOM_ID", "Failed to change the room's name. Your room no longer exists."},
{REC_CHANGE_ROOM_NAME_NOT_IN_ROOM, "REC_CHANGE_ROOM_NAME_NOT_IN_ROOM", "Failed to change the room's name. You are not in a room."},
{REC_CHANGE_ROOM_NAME_MUST_BE_MODERATOR, "REC_CHANGE_ROOM_NAME_MUST_BE_MODERATOR", "Failed to change the room's name. You must be moderator to do this."},
{REC_CHANGE_ROOM_NAME_HAS_PROFANITY, "REC_CHANGE_ROOM_NAME_HAS_PROFANITY", "Failed to change the room's name. The new name contains profanity."},
{REC_CHANGE_ROOM_NAME_EMPTY_ROOM_NAME, "REC_CHANGE_ROOM_NAME_EMPTY_ROOM_NAME", "Failed to change the room's name. The new name is empty."},
{REC_CHANGE_ROOM_NAME_NAME_ALREADY_IN_USE, "REC_CHANGE_ROOM_NAME_NAME_ALREADY_IN_USE", "Failed to change the room's name. The new name is already in use."},
{REC_SET_HIDDEN_FROM_SEARCHES_UNKNOWN_ROOM_ID, "REC_SET_HIDDEN_FROM_SEARCHES_UNKNOWN_ROOM_ID", "Failed to set the room hidden from searches. Your room no longer exists."},
{REC_SET_HIDDEN_FROM_SEARCHES_NOT_IN_ROOM, "REC_SET_HIDDEN_FROM_SEARCHES_NOT_IN_ROOM", "Failed to set the room hidden from searches. You are not in a room."},
{REC_SET_HIDDEN_FROM_SEARCHES_MUST_BE_MODERATOR, "REC_SET_HIDDEN_FROM_SEARCHES_MUST_BE_MODERATOR", "Failed to set the room hidden from searches. You must be moderator to do this."},
{REC_SET_DESTROY_ON_MODERATOR_LEAVE_UNKNOWN_ROOM_ID, "REC_SET_DESTROY_ON_MODERATOR_LEAVE_UNKNOWN_ROOM_ID", "Failed to set the room to be destroyed on moderator leave. Your room no longer exists."},
{REC_SET_DESTROY_ON_MODERATOR_LEAVE_NOT_IN_ROOM, "REC_SET_DESTROY_ON_MODERATOR_LEAVE_NOT_IN_ROOM", "Failed to set the room to be destroyed on moderator leave. You are not in a room."},
{REC_SET_DESTROY_ON_MODERATOR_LEAVE_MUST_BE_MODERATOR, "REC_SET_DESTROY_ON_MODERATOR_LEAVE_MUST_BE_MODERATOR", "Failed to set the room to be destroyed on moderator leave. You must be moderator to do this."},
{REC_SET_READY_STATUS_UNKNOWN_ROOM_ID, "REC_SET_READY_STATUS_UNKNOWN_ROOM_ID", "Failed to set ready status. Your room no longer exists."},
{REC_SET_READY_STATUS_NOT_IN_ROOM, "REC_SET_READY_STATUS_NOT_IN_ROOM,", "Failed to set ready status. You are not in a room."},
{REC_SET_READY_STATUS_NOT_IN_PLAYABLE_SLOT, "REC_SET_READY_STATUS_NOT_IN_PLAYABLE_SLOT", "Failed to set ready status. You are currently spectating. Only players can set ready status."},
{REC_SET_READY_STATUS_AUTO_LOCK_ALL_PLAYERS_READY, "REC_SET_READY_STATUS_AUTO_LOCK_ALL_PLAYERS_READY", "Failed to unready. The room is locked. Leave the room if you do not want to play."},
{REC_GET_READY_STATUS_NOT_IN_ROOM, "REC_GET_READY_STATUS_NOT_IN_ROOM", "Failed to get ready status for your existing room. You are not in a room."},
{REC_GET_READY_STATUS_UNKNOWN_ROOM_ID, "REC_GET_READY_STATUS_UNKNOWN_ROOM_ID,", "Failed to get ready status. Your room no longer exists."},
{REC_SET_ROOM_LOCK_STATE_UNKNOWN_ROOM_ID, "REC_SET_ROOM_LOCK_STATE_UNKNOWN_ROOM_ID", "Failed to set room lock state. Your room no longer exists."},
{REC_SET_ROOM_LOCK_STATE_NOT_IN_ROOM, "REC_SET_ROOM_LOCK_STATE_NOT_IN_ROOM", "Failed to set room lock state. You are not in a room."},
{REC_SET_ROOM_LOCK_STATE_MUST_BE_MODERATOR, "REC_SET_ROOM_LOCK_STATE_MUST_BE_MODERATOR", "Failed to set room lock state. You must be moderator to do this."},
{REC_SET_ROOM_LOCK_STATE_BAD_ENUMERATION_VALUE, "REC_SET_ROOM_LOCK_STATE_BAD_ENUMERATION_VALUE", "Failed to set room lock state. Bad enumeration (programmer error)."},
{REC_GET_ROOM_LOCK_STATE_UNKNOWN_ROOM_ID, "REC_GET_ROOM_LOCK_STATE_UNKNOWN_ROOM_ID", "Failed to get room lock state. Your room no longer exists."},
{REC_GET_ROOM_LOCK_STATE_NOT_IN_ROOM, "REC_GET_ROOM_LOCK_STATE_NOT_IN_ROOM", "Failed to get room lock state for your existing room. You are not in a room."},
{REC_ARE_ALL_MEMBERS_READY_UNKNOWN_ROOM_ID, "REC_ARE_ALL_MEMBERS_READY_UNKNOWN_ROOM_ID", "Failed to check member ready status. Your room no longer exists."},
{REC_ARE_ALL_MEMBERS_READY_NOT_IN_ROOM, "REC_ARE_ALL_MEMBERS_READY_NOT_IN_ROOM", "Failed to check member ready status for your existing room. You are not in a room."},
{REC_KICK_MEMBER_UNKNOWN_ROOM_ID, "REC_KICK_MEMBER_UNKNOWN_ROOM_ID", "Failed to kick member. Your room no longer exists."},
{REC_KICK_MEMBER_NOT_IN_ROOM, "REC_KICK_MEMBER_NOT_IN_ROOM", "Failed to kick member. You are not in a room."},
{REC_KICK_MEMBER_TARGET_NOT_ONLINE, "REC_KICK_MEMBER_TARGET_NOT_ONLINE", "Failed to kick member. The target member is not online."},
{REC_KICK_MEMBER_TARGET_NOT_IN_YOUR_ROOM, "REC_KICK_MEMBER_TARGET_NOT_IN_YOUR_ROOM", "Failed to kick member. Member is no longer in the room."},
{REC_KICK_MEMBER_MUST_BE_MODERATOR, "REC_KICK_MEMBER_MUST_BE_MODERATOR", "Failed to kick member. You must be moderator to do this."},
{REC_KICK_MEMBER_CANNOT_PERFORM_ON_SELF, "REC_KICK_MEMBER_CANNOT_PERFORM_ON_SELF", "Cannot kick yourself."},
{REC_GET_KICK_REASON_UNKNOWN_ROOM_ID, "REC_GET_KICK_REASON_UNKNOWN_ROOM_ID", "Failed to get kick reason. Your room no longer exists."},
{REC_GET_KICK_REASON_NOT_KICKED, "REC_GET_KICK_REASON_NOT_KICKED", "Specified user has not been kicked."},
{REC_REMOVE_USER_NOT_IN_ROOM, "REC_REMOVE_USER_NOT_IN_ROOM", "Failed to remove user from room. User is not in room."},
{REC_ADD_TITLE_ALREADY_IN_USE, "REC_ADD_TITLE_ALREADY_IN_USE", "Failed to add a title. This title is already in use."},
{REC_UNBAN_MEMBER_UNKNOWN_ROOM_ID, "REC_UNBAN_MEMBER_UNKNOWN_ROOM_ID", "Failed to unban member. Your room no longer exists."},
{REC_UNBAN_MEMBER_NOT_IN_ROOM, "REC_UNBAN_MEMBER_NOT_IN_ROOM", "Failed to unban member. You are not in a room."},
{REC_UNBAN_MEMBER_MUST_BE_MODERATOR, "REC_UNBAN_MEMBER_MUST_BE_MODERATOR", "Failed to unban member. You must be moderator to do this."},
{REC_UNBAN_MEMBER_NOT_BANNED, "REC_UNBAN_MEMBER_NOT_BANNED", "Specified member is not banned."},
{REC_GET_BAN_REASON_UNKNOWN_ROOM_ID, "REC_GET_BAN_REASON_UNKNOWN_ROOM_ID", "Failed to get ban reason. Room no longer exists."},
{REC_GET_BAN_REASON_NOT_BANNED, "REC_GET_BAN_REASON_NOT_BANNED", "This user is not banned."},
{REC_CHANGE_HANDLE_NEW_HANDLE_IN_USE, "REC_CHANGE_HANDLE_NEW_HANDLE_IN_USE", "The handle you are changing to is already in use."},
{REC_CHANGE_HANDLE_CONTAINS_PROFANITY, "REC_CHANGE_HANDLE_CONTAINS_PROFANITY", "The handle you are changing to contains profanity."},
{REC_CHAT_USER_NOT_IN_ROOM, "REC_CHAT_USER_NOT_IN_ROOM", "You must be in a room to send room chat messages."},
{REC_CHAT_RECIPIENT_NOT_ONLINE, "REC_CHAT_RECIPIENT_NOT_ONLINE,", "Chat recipient is not online."},
{REC_CHAT_RECIPIENT_NOT_IN_ANY_ROOM, "REC_CHAT_RECIPIENT_NOT_IN_ANY_ROOM", "Chat recipient is not in a room."},
{REC_CHAT_RECIPIENT_NOT_IN_YOUR_ROOM, "REC_CHAT_RECIPIENT_NOT_IN_YOUR_ROOM", "Chat recipient is not in your room."},
{REC_BITSTREAM_USER_NOT_IN_ROOM, "REC_BITSTREAM_USER_NOT_IN_ROOM", "You must be in a room to send bitstream messages."},
{REC_BITSTREAM_RECIPIENT_NOT_ONLINE, "REC_BITSTREAM_RECIPIENT_NOT_ONLINE", "Bitstream recipient is not online."},
{REC_BITSTREAM_RECIPIENT_NOT_IN_ANY_ROOM, "REC_BITSTREAM_RECIPIENT_NOT_IN_ANY_ROOM", "Bitstream recipient is not in a room."},
{REC_BITSTREAM_RECIPIENT_NOT_IN_YOUR_ROOM, "REC_BITSTREAM_RECIPIENT_NOT_IN_YOUR_ROOM", "Bitstream recipient is not in your room."},
};
const char *RoomsErrorCodeDescription::ToEnglish(RoomsErrorCode result)
{
RakAssert(errorCodeDescriptions[result].errorCode==result);
return errorCodeDescriptions[result].englishDesc;
}
const char *RoomsErrorCodeDescription::ToEnum(RoomsErrorCode result)
{
RakAssert(errorCodeDescriptions[result].errorCode==result);
return errorCodeDescriptions[result].enumDesc;
}
void RoomsErrorCodeDescription::Validate(void)
{
int i;
for (i=0; i < ROOMS_ERROR_CODES_COUNT; i++)
{
RakAssert(errorCodeDescriptions[i].errorCode==i);
}
}

View File

@ -0,0 +1,193 @@
/*
* Original work: Copyright (c) 2014, Oculus VR, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* RakNet License.txt file in the licenses directory of this source tree. An additional grant
* of patent rights can be found in the RakNet Patents.txt file in the same directory.
*
*
* Modified work: Copyright (c) 2017-2018, SLikeSoft UG (haftungsbeschränkt)
*
* This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
* license found in the license.txt file in the root directory of this source tree.
*/
#ifndef __ROOMS_ERROR_CODES_H
#define __ROOMS_ERROR_CODES_H
#include "slikenet/defines.h" // used for SLNet -> RakNet namespace change in RAKNET_COMPATIBILITY mode
namespace SLNet
{
enum RoomsErrorCode
{
REC_SUCCESS,
REC_USERNAME_IS_EMPTY, // Generic error, when the requester of an operation did not define his username
REC_NOT_LOGGED_IN, // Generic error, when the requester of an operation is not logged in
REC_ADD_TO_ROOM_NO_RESERVED_OR_PUBLIC,
REC_ADD_TO_ROOM_NO_PUBLIC,
REC_ADD_TO_ROOM_NO_SPECTATOR,
REC_ADD_TO_ROOM_ALREADY_IN_THIS_ROOM,
REC_ADD_TO_ROOM_ALREADY_IN_ANOTHER_ROOM,
REC_ADD_TO_ROOM_KICKED_OUT_OF_ROOM,
REC_CHANGE_MEMBER_TYPE_NO_SLOTS,
REC_SEARCH_BY_FILTER_UNKNOWN_TITLE,
REC_JOIN_BY_FILTER_UNKNOWN_TITLE,
REC_JOIN_BY_FILTER_NO_ROOMS,
REC_JOIN_BY_FILTER_CURRENTLY_IN_A_ROOM,
REC_JOIN_BY_FILTER_CURRENTLY_IN_QUICK_JOIN,
REC_JOIN_BY_FILTER_CANNOT_JOIN_AS_MODERATOR,
REC_JOIN_BY_FILTER_ROOM_LOCKED,
REC_JOIN_BY_FILTER_BANNED,
REC_JOIN_BY_FILTER_NO_SLOTS,
REC_JOIN_BY_QUICK_JOIN_CANNOT_JOIN_AS_MODERATOR,
REC_JOIN_BY_QUICK_JOIN_ROOM_LOCKED,
REC_JOIN_BY_QUICK_JOIN_BANNED,
REC_JOIN_BY_QUICK_JOIN_NO_SLOTS,
REC_ADD_TO_QUICK_JOIN_CURRENTLY_IN_A_ROOM,
REC_ADD_TO_QUICK_JOIN_UNKNOWN_TITLE,
REC_ADD_TO_QUICK_JOIN_ALREADY_THERE,
REC_ADD_TO_QUICK_JOIN_INVALID_TIMEOUT_TOO_LOW,
REC_ADD_TO_QUICK_JOIN_INVALID_TIMEOUT_TOO_HIGH,
REC_ADD_TO_QUICK_JOIN_MINIMUM_SLOTS_TOO_LOW,
REC_ADD_TO_QUICK_JOIN_MINIMUM_SLOTS_TOO_HIGH,
REC_REMOVE_FROM_QUICK_UNKNOWN_TITLE,
REC_REMOVE_FROM_QUICK_JOIN_NOT_THERE,
REC_CREATE_ROOM_UNKNOWN_TITLE,
REC_CREATE_ROOM_CURRENTLY_IN_QUICK_JOIN,
REC_CREATE_ROOM_CURRENTLY_IN_A_ROOM,
REC_ROOM_CREATION_PARAMETERS_EMPTY_ROOM_NAME,
REC_ROOM_CREATION_PARAMETERS_RESERVED_QUICK_JOIN_ROOM_NAME,
REC_ROOM_CREATION_PARAMETERS_ROOM_NAME_HAS_PROFANITY,
REC_ROOM_CREATION_PARAMETERS_ROOM_NAME_IN_USE,
REC_ROOM_CREATION_PARAMETERS_NO_PLAYABLE_SLOTS,
REC_SET_ROOM_PROPERTIES_UNKNOWN_ROOM,
REC_LEAVE_ROOM_UNKNOWN_ROOM_ID,
REC_LEAVE_ROOM_CURRENTLY_IN_QUICK_JOIN,
REC_LEAVE_ROOM_NOT_IN_ROOM,
REC_ENTER_ROOM_UNKNOWN_TITLE,
REC_ENTER_ROOM_CURRENTLY_IN_QUICK_JOIN,
REC_ENTER_ROOM_CURRENTLY_IN_A_ROOM,
REC_PROCESS_QUICK_JOINS_UNKNOWN_TITLE,
REC_ROOM_QUERY_TOO_MANY_QUERIES,
REC_ROOM_QUERY_INVALID_QUERIES_POINTER,
REC_SEND_INVITE_UNKNOWN_ROOM_ID,
REC_SEND_INVITE_INVITEE_ALREADY_INVITED,
REC_SEND_INVITE_CANNOT_PERFORM_ON_SELF,
REC_SEND_INVITE_INVITOR_ONLY_MODERATOR_CAN_INVITE, // INVITE_MODE_MODERATOR_ONLY
REC_SEND_INVITE_INVITOR_LACK_INVITE_PERMISSIONS, // Any other INVITE_MODE
REC_SEND_INVITE_INVITOR_NOT_IN_ROOM,
REC_SEND_INVITE_NO_SLOTS,
REC_SEND_INVITE_INVITEE_ALREADY_IN_THIS_ROOM,
REC_SEND_INVITE_INVITEE_BANNED,
REC_SEND_INVITE_RECIPIENT_NOT_ONLINE,
REC_SEND_INVITE_ROOM_LOCKED,
REC_ACCEPT_INVITE_UNKNOWN_ROOM_ID,
REC_ACCEPT_INVITE_CURRENTLY_IN_A_ROOM,
REC_ACCEPT_INVITE_CURRENTLY_IN_QUICK_JOIN,
REC_ACCEPT_INVITE_BANNED,
REC_ACCEPT_INVITE_NO_SLOTS,
REC_ACCEPT_INVITE_ROOM_LOCKED,
REC_ACCEPT_INVITE_NO_SUCH_INVITE,
REC_SLOTS_VALIDATION_NO_PLAYABLE_SLOTS,
REC_SLOTS_VALIDATION_NEGATIVE_PUBLIC_SLOTS,
REC_SLOTS_VALIDATION_NEGATIVE_RESERVED_SLOTS,
REC_SLOTS_VALIDATION_NEGATIVE_SPECTATOR_SLOTS,
REC_START_SPECTATING_UNKNOWN_ROOM_ID,
REC_START_SPECTATING_ALREADY_SPECTATING,
REC_START_SPECTATING_NO_SPECTATOR_SLOTS_AVAILABLE,
REC_START_SPECTATING_NOT_IN_ROOM,
REC_START_SPECTATING_REASSIGN_MODERATOR_BEFORE_SPECTATE,
REC_START_SPECTATING_ROOM_LOCKED,
REC_STOP_SPECTATING_UNKNOWN_ROOM_ID,
REC_STOP_SPECTATING_NOT_IN_ROOM,
REC_STOP_SPECTATING_NOT_CURRENTLY_SPECTATING,
REC_STOP_SPECTATING_NO_SLOTS,
REC_STOP_SPECTATING_ROOM_LOCKED,
REC_GRANT_MODERATOR_UNKNOWN_ROOM_ID,
REC_GRANT_MODERATOR_NEW_MODERATOR_NOT_ONLINE,
REC_GRANT_MODERATOR_NOT_IN_ROOM,
REC_GRANT_MODERATOR_NEW_MODERATOR_NOT_IN_ROOM,
REC_GRANT_MODERATOR_CANNOT_PERFORM_ON_SELF,
REC_GRANT_MODERATOR_MUST_BE_MODERATOR_TO_GRANT_MODERATOR,
REC_GRANT_MODERATOR_NEW_MODERATOR_NOT_IN_PLAYABLE_SLOT,
REC_CHANGE_SLOT_COUNTS_UNKNOWN_ROOM_ID,
REC_CHANGE_SLOT_COUNTS_NOT_IN_ROOM,
REC_CHANGE_SLOT_COUNTS_MUST_BE_MODERATOR,
REC_SET_CUSTOM_ROOM_PROPERTIES_UNKNOWN_ROOM_ID,
REC_SET_CUSTOM_ROOM_PROPERTIES_CONTAINS_DEFAULT_COLUMNS,
REC_SET_CUSTOM_ROOM_PROPERTIES_NOT_IN_ROOM,
REC_SET_CUSTOM_ROOM_PROPERTIES_MUST_BE_MODERATOR,
REC_GET_ROOM_PROPERTIES_EMPTY_ROOM_NAME_AND_NOT_IN_A_ROOM,
REC_GET_ROOM_PROPERTIES_UNKNOWN_ROOM_NAME,
REC_CHANGE_ROOM_NAME_UNKNOWN_ROOM_ID,
REC_CHANGE_ROOM_NAME_NOT_IN_ROOM,
REC_CHANGE_ROOM_NAME_MUST_BE_MODERATOR,
REC_CHANGE_ROOM_NAME_HAS_PROFANITY,
REC_CHANGE_ROOM_NAME_EMPTY_ROOM_NAME,
REC_CHANGE_ROOM_NAME_NAME_ALREADY_IN_USE,
REC_SET_HIDDEN_FROM_SEARCHES_UNKNOWN_ROOM_ID,
REC_SET_HIDDEN_FROM_SEARCHES_NOT_IN_ROOM,
REC_SET_HIDDEN_FROM_SEARCHES_MUST_BE_MODERATOR,
REC_SET_DESTROY_ON_MODERATOR_LEAVE_UNKNOWN_ROOM_ID,
REC_SET_DESTROY_ON_MODERATOR_LEAVE_NOT_IN_ROOM,
REC_SET_DESTROY_ON_MODERATOR_LEAVE_MUST_BE_MODERATOR,
REC_SET_READY_STATUS_UNKNOWN_ROOM_ID,
REC_SET_READY_STATUS_NOT_IN_ROOM,
REC_SET_READY_STATUS_NOT_IN_PLAYABLE_SLOT,
REC_SET_READY_STATUS_AUTO_LOCK_ALL_PLAYERS_READY,
REC_GET_READY_STATUS_NOT_IN_ROOM,
REC_GET_READY_STATUS_UNKNOWN_ROOM_ID,
REC_SET_ROOM_LOCK_STATE_UNKNOWN_ROOM_ID,
REC_SET_ROOM_LOCK_STATE_NOT_IN_ROOM,
REC_SET_ROOM_LOCK_STATE_MUST_BE_MODERATOR,
REC_SET_ROOM_LOCK_STATE_BAD_ENUMERATION_VALUE,
REC_GET_ROOM_LOCK_STATE_UNKNOWN_ROOM_ID,
REC_GET_ROOM_LOCK_STATE_NOT_IN_ROOM,
REC_ARE_ALL_MEMBERS_READY_UNKNOWN_ROOM_ID,
REC_ARE_ALL_MEMBERS_READY_NOT_IN_ROOM,
REC_KICK_MEMBER_UNKNOWN_ROOM_ID,
REC_KICK_MEMBER_NOT_IN_ROOM,
REC_KICK_MEMBER_TARGET_NOT_ONLINE,
REC_KICK_MEMBER_TARGET_NOT_IN_YOUR_ROOM,
REC_KICK_MEMBER_MUST_BE_MODERATOR,
REC_KICK_MEMBER_CANNOT_PERFORM_ON_SELF,
REC_GET_KICK_REASON_UNKNOWN_ROOM_ID,
REC_GET_KICK_REASON_NOT_KICKED,
REC_REMOVE_USER_NOT_IN_ROOM,
REC_ADD_TITLE_ALREADY_IN_USE,
REC_UNBAN_MEMBER_UNKNOWN_ROOM_ID,
REC_UNBAN_MEMBER_NOT_IN_ROOM,
REC_UNBAN_MEMBER_MUST_BE_MODERATOR,
REC_UNBAN_MEMBER_NOT_BANNED,
REC_GET_BAN_REASON_UNKNOWN_ROOM_ID,
REC_GET_BAN_REASON_NOT_BANNED,
REC_CHANGE_HANDLE_NEW_HANDLE_IN_USE,
REC_CHANGE_HANDLE_CONTAINS_PROFANITY,
REC_CHAT_USER_NOT_IN_ROOM,
REC_CHAT_RECIPIENT_NOT_ONLINE,
REC_CHAT_RECIPIENT_NOT_IN_ANY_ROOM,
REC_CHAT_RECIPIENT_NOT_IN_YOUR_ROOM,
REC_BITSTREAM_USER_NOT_IN_ROOM,
REC_BITSTREAM_RECIPIENT_NOT_ONLINE,
REC_BITSTREAM_RECIPIENT_NOT_IN_ANY_ROOM,
REC_BITSTREAM_RECIPIENT_NOT_IN_YOUR_ROOM,
ROOMS_ERROR_CODES_COUNT
};
struct RoomsErrorCodeDescription
{
RoomsErrorCode errorCode;
const char *enumDesc;
const char *englishDesc;
static const char *ToEnglish(RoomsErrorCode result);
static const char *ToEnum(RoomsErrorCode result);
static void Validate(void);
};
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff