Browse Source

Implement command parsing

nordsoft 3 years ago
parent
commit
75613a947d
3 changed files with 202 additions and 13 deletions
  1. 145 9
      launcher/lobby/lobby_moc.cpp
  2. 48 4
      launcher/lobby/lobby_moc.h
  3. 9 0
      launcher/lobby/lobby_moc.ui

+ 145 - 9
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::on_messageEdit_returnPressed()
+void Lobby::serverCommand(const ServerCommand & command) try
 {
-	socketLobby.send(ProtocolStrings[MESSAGE].arg(ui->messageEdit->text()));
-	ui->messageEdit->clear();
+	//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::text(QString txt)
+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::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());
+}
+

+ 48 - 4
launcher/lobby/lobby_moc.h

@@ -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

+ 9 - 0
launcher/lobby/lobby_moc.ui

@@ -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>