1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
/*
* lobby.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include <QTcpSocket>
#include <QAbstractSocket>
const unsigned int ProtocolVersion = 3;
const std::string ProtocolEncoding = "utf8";
class ProtocolError: public std::runtime_error
{
public:
ProtocolError(const char * w): std::runtime_error(w) {}
};
enum ProtocolConsts
{
//client consts
GREETING, USERNAME, MESSAGE, VERSION, CREATE, JOIN, LEAVE, KICK, READY, FORCESTART,
//server consts
SESSIONS, CREATED, JOINED, KICKED, SRVERROR, CHAT, START, STATUS, HOST, MODS, CLIENTMODS
};
const QMap<ProtocolConsts, QString> ProtocolStrings
{
//=== client commands ===
//handshaking with server
//%1: first byte is protocol_version, then size of encoding string in bytes, then encoding string
//%2: client name
//%3: VCMI version
{GREETING, "%1<GREETINGS>%2<VER>%3"},
//[unsupported] autorization with username
//%1: username
{USERNAME, "<USER>%1"},
//sending message to the chat
//%1: message text
{MESSAGE, "<MSG>%1"},
//create new room
//%1: room name
//%2: password for the room
//%3: max number of players
//%4: mods used by host
// each mod has a format modname&modversion, mods should be separated by ; symbol
{CREATE, "<NEW>%1<PSWD>%2<COUNT>%3<MODS>%4"},
//join to the room
//%1: room name
//%2: password for the room
//%3: list of mods used by player
// each mod has a format modname&modversion, mods should be separated by ; symbol
{JOIN, "<JOIN>%1<PSWD>%2<MODS>%3"},
//leave the room
//%1: room name
{LEAVE, "<LEAVE>%1"},
//kick user from the current room
//%1: player username
{KICK, "<KICK>%1"},
//signal that player is ready for game
//%1: room name
{READY, "<READY>%1"},
//[unsupported] start session immediately
//%1: room name
{FORCESTART, "<FORCESTART>%1"},
//=== server commands ===
//server commands are started from :>>, arguments are enumerated by : symbol
//new session was created
//arg[0]: room name
{CREATED, "CREATED"},
//list of existing sessions
//arg[0]: amount of sessions, following arguments depending on it
//arg[x]: session name
//arg[x+1]: amount of players in the session
//arg[x+2]: total amount of players allowed
//arg[x+3]: True if session is protected by password
{SESSIONS, "SESSIONS"},
//user has joined to the session
//arg[0]: session name
//arg[1]: username (who was joined)
{JOINED, "JOIN"},
//user has left the session
//arg[0]: session name
//arg[1]: username (who has left)
{KICKED, "KICK"},
//session has been started
//arg[0]: session name
//arg[1]: uuid to be used for connection
{START, "START"},
//host ownership for the game session
//arg[0]: uuid to be used by vcmiserver
//arg[1]: amount of players (clients) to be connected
{HOST, "HOST"},
//room status
//arg[0]: amount of players, following arguments depending on it
//arg[x]: player username
//arg[x+1]: True if player is ready
{STATUS, "STATUS"}, //joined_players:player_name:is_ready
//server error
//arg[0]: error message
{SRVERROR, "ERROR"},
//mods used in the session by host player
//arg[0]: amount of mods, following arguments depending on it
//arg[x]: mod name
//arg[x+1]: mod version
{MODS, "MODS"},
//mods used by user
//arg[0]: username
//arg[1]: amount of mods, following arguments depending on it
//arg[x]: mod name
//arg[x+1]: mod version
{CLIENTMODS, "MODSOTHER"},
//received chat message
//arg[0]: sender username
//arg[1]: message text
{CHAT, "MSG"}
};
class ServerCommand
{
public:
ServerCommand(ProtocolConsts, const QStringList & arguments);
const ProtocolConsts command;
const QStringList arguments;
};
class SocketLobby : public QObject
{
Q_OBJECT
public:
explicit SocketLobby(QObject *parent = 0);
void connectServer(const QString & host, int port, const QString & username, int timeout);
void disconnectServer();
void requestNewSession(const QString & session, int totalPlayers, const QString & pswd, const QMap<QString, QString> & mods);
void requestJoinSession(const QString & session, const QString & pswd, const QMap<QString, QString> & mods);
void requestLeaveSession(const QString & session);
void requestReadySession(const QString & session);
void send(const QString &);
signals:
void text(QString);
void receive(QString);
void disconnect();
public slots:
void connected();
void disconnected();
void bytesWritten(qint64 bytes);
void readyRead();
private:
QTcpSocket *socket;
bool isConnected = false;
QString username;
};
QString prepareModsClientString(const QMap<QString, QString> & mods);
|