From 75613a947d47e2fa0f6b1bf4bd762e51431b8083 Mon Sep 17 00:00:00 2001 From: nordsoft Date: Sun, 23 Oct 2022 02:55:22 +0400 Subject: [PATCH] Implement command parsing --- launcher/lobby/lobby_moc.cpp | 160 ++++++++++++++++++++++++++++++++--- launcher/lobby/lobby_moc.h | 52 +++++++++++- launcher/lobby/lobby_moc.ui | 9 ++ 3 files changed, 205 insertions(+), 16 deletions(-) diff --git a/launcher/lobby/lobby_moc.cpp b/launcher/lobby/lobby_moc.cpp index 5f9aeca84..76d44cde2 100644 --- a/launcher/lobby/lobby_moc.cpp +++ b/launcher/lobby/lobby_moc.cpp @@ -32,6 +32,18 @@ void SocketLobby::disconnectServer() socket->disconnectFromHost(); } +void SocketLobby::requestNewSession(const QString & session, int totalPlayers, const QString & pswd) +{ + const QString sessionMessage = ProtocolStrings[CREATE].arg(session, pswd, QString::number(totalPlayers)); + send(sessionMessage); +} + +void SocketLobby::requestJoinSession(const QString & session, const QString & pswd) +{ + const QString sessionMessage = ProtocolStrings[JOIN].arg(session, pswd); + send(sessionMessage); +} + void SocketLobby::send(const QString & msg) { socket->write(qPrintable(msg)); @@ -42,7 +54,7 @@ void SocketLobby::connected() isConnected = true; emit text("Connected!"); - const QString greetingConst = ProtocolStrings[GREETING].arg(username) + ProtocolStrings[VERSION].arg(QString::fromStdString(GameConstants::VCMI_VERSION)); + const QString greetingConst = ProtocolStrings[GREETING].arg(username, QString::fromStdString(GameConstants::VCMI_VERSION)); send(greetingConst); } @@ -60,11 +72,15 @@ void SocketLobby::bytesWritten(qint64 bytes) void SocketLobby::readyRead() { qDebug() << "Reading..."; - emit text(socket->readAll()); + emit receive(socket->readAll()); } - +ServerCommand::ServerCommand(ProtocolConsts cmd, const QStringList & args): + command(cmd), + arguments(args) +{ +} Lobby::Lobby(QWidget *parent) : QWidget(parent), @@ -72,7 +88,8 @@ Lobby::Lobby(QWidget *parent) : { ui->setupUi(this); - connect(&socketLobby, SIGNAL(text(QString)), this, SLOT(text(QString))); + connect(&socketLobby, SIGNAL(text(QString)), this, SLOT(chatMessage(QString))); + connect(&socketLobby, SIGNAL(receive(QString)), this, SLOT(dispatchMessage(QString))); } Lobby::~Lobby() @@ -80,24 +97,128 @@ Lobby::~Lobby() delete ui; } +void Lobby::serverCommand(const ServerCommand & command) try +{ + //initialize variables outside of switch block + const auto & args = command.arguments; + int amount, tagPoint; + QString joinStr; + switch(command.command) + { + case ERROR: + protocolAssert(args.size()); + chatMessage("System error:" + args[0]); + break; + + case CREATED: + protocolAssert(args.size()); + hostSession = args[0]; + session = args[0]; + chatMessage("System: new session started"); + break; + + case SESSIONS: + protocolAssert(args.size()); + amount = args[0].toInt(); + protocolAssert(amount * 4 == (args.size() - 1)); + ui->sessionsTable->setRowCount(amount); + + tagPoint = 1; + for(int i = 0; i < amount; ++i) + { + QTableWidgetItem * sessionNameItem = new QTableWidgetItem(args[tagPoint++]); + ui->sessionsTable->setItem(i, 0, sessionNameItem); + + int playersJoined = args[tagPoint++].toInt(); + int playersTotal = args[tagPoint++].toInt(); + QTableWidgetItem * sessionPlayerItem = new QTableWidgetItem(QString("%1/%2").arg(playersJoined).arg(playersTotal)); + ui->sessionsTable->setItem(i, 1, sessionPlayerItem); + + QTableWidgetItem * sessionProtectedItem = new QTableWidgetItem(args[tagPoint++]); + ui->sessionsTable->setItem(i, 2, sessionProtectedItem); + } + + break; + + case JOINED: + case KICKED: + protocolAssert(args.size() == 2); + joinStr = (command.command == JOINED ? "System: %1 joined to the session %2" : "System: %1 left session %2"); + + if(args[1] == username) + { + chatMessage(joinStr.arg("you", args[0])); + } + else + { + chatMessage(joinStr.arg(args[1], args[0])); + } + break; + + case CHAT: + protocolAssert(args.size() > 1); + QString msg; + for(int i = 1; i < args.size(); ++i) + msg += args[i]; + chatMessage(QString("%1: %2").arg(args[0], msg)); + break; + } +} +catch(const ProtocolError & e) +{ + chatMessage(QString("System error: %1").arg(e.what())); +} + +void Lobby::dispatchMessage(QString txt) try +{ + if(txt.isEmpty()) + return; + + QStringList parseTags = txt.split(":>>"); + protocolAssert(parseTags.size() > 1 && parseTags[0].isEmpty() && !parseTags[1].isEmpty()); + + for(int c = 1; c < parseTags.size(); ++c) + { + QStringList parseArgs = parseTags[c].split(":"); + protocolAssert(parseArgs.size() > 1); + + auto ctype = ProtocolStrings.key(parseArgs[0]); + parseArgs.pop_front(); + ServerCommand cmd(ctype, parseArgs); + serverCommand(cmd); + } +} +catch(const ProtocolError & e) +{ + chatMessage(QString("System error: %1").arg(e.what())); +} + + +void Lobby::chatMessage(QString txt) +{ + QTextCursor curs(ui->chat->document()); + curs.movePosition(QTextCursor::End); + curs.insertText(txt + "\n"); +} + +void Lobby::protocolAssert(bool expr) +{ + if(!expr) + throw ProtocolError("Protocol error"); +} + void Lobby::on_messageEdit_returnPressed() { socketLobby.send(ProtocolStrings[MESSAGE].arg(ui->messageEdit->text())); ui->messageEdit->clear(); } -void Lobby::text(QString txt) -{ - QTextCursor curs(ui->chat->document()); - curs.movePosition(QTextCursor::End); - curs.insertText(txt + "\n"); -} - void Lobby::on_connectButton_toggled(bool checked) { if(checked) { - socketLobby.connectServer(ui->hostEdit->text(), ui->portEdit->text().toInt(), ui->userEdit->text()); + username = ui->userEdit->text(); + socketLobby.connectServer(ui->hostEdit->text(), ui->portEdit->text().toInt(), username); } else { @@ -105,3 +226,18 @@ void Lobby::on_connectButton_toggled(bool checked) } } +void Lobby::on_newButton_clicked() +{ + bool ok; + QString sessionName = QInputDialog::getText(this, tr("New session"), tr("Session name:"), QLineEdit::Normal, "", &ok); + if(ok && !sessionName.isEmpty()) + socketLobby.requestNewSession(sessionName, 2, ui->passwordInput->text()); +} + +void Lobby::on_joinButton_clicked() +{ + auto * item = ui->sessionsTable->item(ui->sessionsTable->currentRow(), 0); + if(item) + socketLobby.requestJoinSession(item->text(), ui->passwordInput->text()); +} + diff --git a/launcher/lobby/lobby_moc.h b/launcher/lobby/lobby_moc.h index 01021bb55..3949dd5d4 100644 --- a/launcher/lobby/lobby_moc.h +++ b/launcher/lobby/lobby_moc.h @@ -5,17 +5,46 @@ #include #include +class ProtocolError: public std::runtime_error +{ +public: + ProtocolError(const char * w): std::runtime_error(w) {} +}; + enum ProtocolConsts { - GREETING, USERNAME, MESSAGE, VERSION + //client consts + GREETING, USERNAME, MESSAGE, VERSION, CREATE, JOIN, + + //server consts + SESSIONS, CREATED, JOINED, KICKED, ERROR, CHAT }; const QMap ProtocolStrings { - {GREETING, "%1"}, + //client consts + {GREETING, "%1%2"}, {USERNAME, "%1"}, {MESSAGE, "%1"}, - {VERSION, "%1"} + {CREATE, "%1%2%3"}, + {JOIN, "%1%2"}, + + //server consts + {CREATED, "CREATED"}, + {SESSIONS, "SESSIONS"}, //amount:session_name:joined_players:total_players:is_protected + {JOINED, "JOIN"}, //session_name:username + {KICKED, "KICK"}, //session_name:username + {ERROR, "ERROR"}, + {CHAT, "MSG"} //username:message +}; + +class ServerCommand +{ +public: + ServerCommand(ProtocolConsts, const QStringList & arguments); + + const ProtocolConsts command; + const QStringList arguments; }; class SocketLobby : public QObject @@ -25,12 +54,15 @@ public: explicit SocketLobby(QObject *parent = 0); void connectServer(const QString & host, int port, const QString & username); void disconnectServer(); + void requestNewSession(const QString & session, int totalPlayers, const QString & pswd); + void requestJoinSession(const QString & session, const QString & pswd); void send(const QString &); signals: void text(QString); + void receive(QString); public slots: @@ -61,13 +93,25 @@ public: private slots: void on_messageEdit_returnPressed(); - void text(QString); + void chatMessage(QString); + void dispatchMessage(QString); + void serverCommand(const ServerCommand &); void on_connectButton_toggled(bool checked); + void on_newButton_clicked(); + + void on_joinButton_clicked(); + private: Ui::Lobby *ui; SocketLobby socketLobby; + QString hostSession; + QString session; + QString username; + +private: + void protocolAssert(bool); }; #endif // LOBBY_MOC_H diff --git a/launcher/lobby/lobby_moc.ui b/launcher/lobby/lobby_moc.ui index 5cf057819..795620a20 100644 --- a/launcher/lobby/lobby_moc.ui +++ b/launcher/lobby/lobby_moc.ui @@ -110,6 +110,15 @@ + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + Session