1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-25 21:38:59 +02:00

Implement command parsing

This commit is contained in:
nordsoft 2022-10-23 02:55:22 +04:00
parent e54c9af24e
commit 75613a947d
3 changed files with 205 additions and 16 deletions

View File

@ -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());
}

View File

@ -5,17 +5,46 @@
#include <QTcpSocket>
#include <QAbstractSocket>
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<ProtocolConsts, QString> ProtocolStrings
{
{GREETING, "<GREETINGS>%1"},
//client consts
{GREETING, "<GREETINGS>%1<VER>%2"},
{USERNAME, "<USER>%1"},
{MESSAGE, "<MSG>%1"},
{VERSION, "<VER>%1"}
{CREATE, "<NEW>%1<PSWD>%2<COUNT>%3"},
{JOIN, "<JOIN>%1<PSWD>%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

View File

@ -110,6 +110,15 @@
</item>
<item row="0" column="0" colspan="2">
<widget class="QTableWidget" name="sessionsTable">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<column>
<property name="text">
<string>Session</string>