mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-28 08:48:48 +02:00
212 lines
5.2 KiB
C++
212 lines
5.2 KiB
C++
/*
|
|
* 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 = 4;
|
|
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, HERE, ALIVE, HOSTMODE,
|
|
|
|
//server consts
|
|
SESSIONS, CREATED, JOINED, KICKED, SRVERROR, CHAT, START, STATUS, HOST, MODS, CLIENTMODS, USERS, HEALTH, GAMEMODE
|
|
};
|
|
|
|
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"},
|
|
|
|
//request user list
|
|
{HERE, "<HERE>"},
|
|
|
|
//used as reponse to healcheck
|
|
{ALIVE, "<ALIVE>"},
|
|
|
|
//host sets game mode (new game or load game)
|
|
//%1: game mode - 0 for new game, 1 for load game
|
|
{HOSTMODE, "<HOSTMODE>%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"},
|
|
|
|
//list of users currently in lobby
|
|
//arg[0]: amount of players, following arguments depend on it
|
|
//arg[x]: username
|
|
//arg[x+1]: room (empty if not in the room)
|
|
{USERS, "USERS"},
|
|
|
|
//healthcheck from server
|
|
{HEALTH, "HEALTH"},
|
|
|
|
//game mode (new game or load game) set by host
|
|
//arg[0]: game mode
|
|
{GAMEMODE, "GAMEMODE"},
|
|
};
|
|
|
|
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);
|