nordsoft пре 2 година
родитељ
комит
05e4188908

+ 14 - 4
launcher/lobby/lobby.cpp

@@ -39,15 +39,15 @@ void SocketLobby::disconnectServer()
 	socket->disconnectFromHost();
 	socket->disconnectFromHost();
 }
 }
 
 
-void SocketLobby::requestNewSession(const QString & session, int totalPlayers, const QString & pswd)
+void SocketLobby::requestNewSession(const QString & session, int totalPlayers, const QString & pswd, const QMap<QString, QString> & mods)
 {
 {
-	const QString sessionMessage = ProtocolStrings[CREATE].arg(session, pswd, QString::number(totalPlayers));
+	const QString sessionMessage = ProtocolStrings[CREATE].arg(session, pswd, QString::number(totalPlayers), prepareModsClientString(mods));
 	send(sessionMessage);
 	send(sessionMessage);
 }
 }
 
 
-void SocketLobby::requestJoinSession(const QString & session, const QString & pswd)
+void SocketLobby::requestJoinSession(const QString & session, const QString & pswd, const QMap<QString, QString> & mods)
 {
 {
-	const QString sessionMessage = ProtocolStrings[JOIN].arg(session, pswd);
+	const QString sessionMessage = ProtocolStrings[JOIN].arg(session, pswd, prepareModsClientString(mods));
 	send(sessionMessage);
 	send(sessionMessage);
 }
 }
 
 
@@ -111,3 +111,13 @@ ServerCommand::ServerCommand(ProtocolConsts cmd, const QStringList & args):
 	arguments(args)
 	arguments(args)
 {
 {
 }
 }
+
+QString prepareModsClientString(const QMap<QString, QString> & mods)
+{
+	QStringList result;
+	for(auto & mod : mods.keys())
+	{
+		result << mod + "&" + mods[mod];
+	}
+	return result.join(";");
+}

+ 9 - 7
launcher/lobby/lobby.h

@@ -12,7 +12,7 @@
 #include <QTcpSocket>
 #include <QTcpSocket>
 #include <QAbstractSocket>
 #include <QAbstractSocket>
 
 
-const unsigned int ProtocolVersion = 1;
+const unsigned int ProtocolVersion = 2;
 const std::string ProtocolEncoding = "utf8";
 const std::string ProtocolEncoding = "utf8";
 
 
 class ProtocolError: public std::runtime_error
 class ProtocolError: public std::runtime_error
@@ -27,7 +27,7 @@ enum ProtocolConsts
 	GREETING, USERNAME, MESSAGE, VERSION, CREATE, JOIN, LEAVE, READY,
 	GREETING, USERNAME, MESSAGE, VERSION, CREATE, JOIN, LEAVE, READY,
 
 
 	//server consts
 	//server consts
-	SESSIONS, CREATED, JOINED, KICKED, SRVERROR, CHAT, START, STATUS, HOST
+	SESSIONS, CREATED, JOINED, KICKED, SRVERROR, CHAT, START, STATUS, HOST, MODS
 };
 };
 
 
 const QMap<ProtocolConsts, QString> ProtocolStrings
 const QMap<ProtocolConsts, QString> ProtocolStrings
@@ -36,8 +36,8 @@ const QMap<ProtocolConsts, QString> ProtocolStrings
 	{GREETING, "%1<GREETINGS>%2<VER>%3"}, //protocol_version byte, encoding bytes, encoding, name, version
 	{GREETING, "%1<GREETINGS>%2<VER>%3"}, //protocol_version byte, encoding bytes, encoding, name, version
 	{USERNAME, "<USER>%1"},
 	{USERNAME, "<USER>%1"},
 	{MESSAGE, "<MSG>%1"},
 	{MESSAGE, "<MSG>%1"},
-	{CREATE, "<NEW>%1<PSWD>%2<COUNT>%3"},
-	{JOIN, "<JOIN>%1<PSWD>%2"},
+	{CREATE, "<NEW>%1<PSWD>%2<COUNT>%3<MODS>%4"}, //last placeholder for the mods
+	{JOIN, "<JOIN>%1<PSWD>%2<MODS>%3"}, //last placeholder for the mods
 	{LEAVE, "<LEAVE>%1"}, //session
 	{LEAVE, "<LEAVE>%1"}, //session
 	{READY, "<READY>%1"}, //session
 	{READY, "<READY>%1"}, //session
 
 
@@ -50,6 +50,7 @@ const QMap<ProtocolConsts, QString> ProtocolStrings
 	{HOST, "HOST"}, //host_uuid:players_count
 	{HOST, "HOST"}, //host_uuid:players_count
 	{STATUS, "STATUS"}, //joined_players:player_name:is_ready
 	{STATUS, "STATUS"}, //joined_players:player_name:is_ready
 	{SRVERROR, "ERROR"},
 	{SRVERROR, "ERROR"},
+	{MODS, "MODS"}, //amount:modname:modversion
 	{CHAT, "MSG"} //username:message
 	{CHAT, "MSG"} //username:message
 };
 };
 
 
@@ -69,8 +70,8 @@ public:
 	explicit SocketLobby(QObject *parent = 0);
 	explicit SocketLobby(QObject *parent = 0);
 	void connectServer(const QString & host, int port, const QString & username, int timeout);
 	void connectServer(const QString & host, int port, const QString & username, int timeout);
 	void disconnectServer();
 	void disconnectServer();
-	void requestNewSession(const QString & session, int totalPlayers, const QString & pswd);
-	void requestJoinSession(const QString & session, const QString & pswd);
+	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 requestLeaveSession(const QString & session);
 	void requestReadySession(const QString & session);
 	void requestReadySession(const QString & session);
 
 
@@ -93,5 +94,6 @@ private:
 	QTcpSocket *socket;
 	QTcpSocket *socket;
 	bool isConnected = false;
 	bool isConnected = false;
 	QString username;
 	QString username;
-
 };
 };
+
+QString prepareModsClientString(const QMap<QString, QString> & mods);

+ 74 - 15
launcher/lobby/lobby_moc.cpp

@@ -4,6 +4,7 @@
 #include "ui_lobby_moc.h"
 #include "ui_lobby_moc.h"
 #include "lobbyroomrequest_moc.h"
 #include "lobbyroomrequest_moc.h"
 #include "../mainwindow_moc.h"
 #include "../mainwindow_moc.h"
+#include "../modManager/cmodlist.h"
 #include "../../lib/CConfigHandler.h"
 #include "../../lib/CConfigHandler.h"
 
 
 Lobby::Lobby(QWidget *parent) :
 Lobby::Lobby(QWidget *parent) :
@@ -27,11 +28,35 @@ Lobby::~Lobby()
 	delete ui;
 	delete ui;
 }
 }
 
 
+QMap<QString, QString> Lobby::buildModsMap() const
+{
+	QMap<QString, QString> result;
+	const auto & modlist = qobject_cast<MainWindow*>(qApp->activeWindow())->getModList();
+	for(auto & modname : modlist.getModList())
+	{
+		auto mod = modlist.getMod(modname);
+		if(mod.isEnabled())
+		{
+			result[modname] = mod.getValue("version").toString();
+		}
+	}
+	return result;
+}
+
+bool Lobby::isModAvailable(const QString & modName, const QString & modVersion) const
+{
+	const auto & modlist = qobject_cast<MainWindow*>(qApp->activeWindow())->getModList();
+	if(!modlist.hasMod(modName))
+		return false;
+
+	auto mod = modlist.getMod(modName);
+	return (mod.isInstalled () || mod.isAvailable()) && (mod.getValue("version") == modVersion);
+}
+
 void Lobby::serverCommand(const ServerCommand & command) try
 void Lobby::serverCommand(const ServerCommand & command) try
 {
 {
 	//initialize variables outside of switch block
 	//initialize variables outside of switch block
 	const QString statusPlaceholder("%1 %2\n");
 	const QString statusPlaceholder("%1 %2\n");
-	QString resText;
 	const auto & args = command.arguments;
 	const auto & args = command.arguments;
 	int amount, tagPoint;
 	int amount, tagPoint;
 	QString joinStr;
 	QString joinStr;
@@ -40,8 +65,8 @@ void Lobby::serverCommand(const ServerCommand & command) try
 	case SRVERROR:
 	case SRVERROR:
 		protocolAssert(args.size());
 		protocolAssert(args.size());
 		chatMessage("System error", args[0], true);
 		chatMessage("System error", args[0], true);
-		if(authentificationStatus == 0)
-			authentificationStatus = 2;
+		if(authentificationStatus == AuthStatus::NONE)
+			authentificationStatus = AuthStatus::ERROR;
 		break;
 		break;
 
 
 	case CREATED:
 	case CREATED:
@@ -98,19 +123,49 @@ void Lobby::serverCommand(const ServerCommand & command) try
 		}
 		}
 		break;
 		break;
 
 
+	case MODS: {
+		protocolAssert(args.size() > 0);
+		amount = args[0].toInt();
+		protocolAssert(amount * 2 == (args.size() - 1));
+
+		tagPoint = 1;
+		ui->modsList->clear();
+		auto enabledMods = buildModsMap();
+		for(int i = 0; i < amount; ++i, tagPoint += 2)
+		{
+			if(enabledMods.contains(args[tagPoint]))
+			{
+				if(enabledMods[args[tagPoint]] == args[tagPoint + 1])
+					enabledMods.remove(args[tagPoint]);
+				else
+					ui->modsList->addItem(new QListWidgetItem(QIcon("icons:mod-update.png"), QString("%1 (v%2)").arg(args[tagPoint], args[tagPoint + 1])));
+			}
+			else if(isModAvailable(args[tagPoint], args[tagPoint + 1]))
+				ui->modsList->addItem(new QListWidgetItem(QIcon("icons:mod-enabled.png"), QString("%1 (v%2)").arg(args[tagPoint], args[tagPoint + 1])));
+			else
+				ui->modsList->addItem(new QListWidgetItem(QIcon("icons:mod-delete.png"), QString("%1 (v%2)").arg(args[tagPoint], args[tagPoint + 1])));
+		}
+		for(auto & remainMod : enabledMods.keys())
+		{
+			ui->modsList->addItem(new QListWidgetItem(QIcon("icons:mod-disabled.png"), QString("%1 (v%2)").arg(remainMod, enabledMods[remainMod])));
+		}
+		if(!ui->modsList->count())
+			ui->modsList->addItem("No issues detected");
+		break;
+		}
+
+
 	case STATUS:
 	case STATUS:
 		protocolAssert(args.size() > 0);
 		protocolAssert(args.size() > 0);
 		amount = args[0].toInt();
 		amount = args[0].toInt();
 		protocolAssert(amount * 2 == (args.size() - 1));
 		protocolAssert(amount * 2 == (args.size() - 1));
 
 
 		tagPoint = 1;
 		tagPoint = 1;
-		ui->roomChat->clear();
-		resText.clear();
+		ui->playersList->clear();
 		for(int i = 0; i < amount; ++i, tagPoint += 2)
 		for(int i = 0; i < amount; ++i, tagPoint += 2)
 		{
 		{
-			resText += statusPlaceholder.arg(args[tagPoint], args[tagPoint + 1] == "True" ? "ready" : "");
+			ui->playersList->addItem(args[tagPoint]);
 		}
 		}
-		ui->roomChat->setPlainText(resText);
 		break;
 		break;
 
 
 	case START: {
 	case START: {
@@ -132,19 +187,23 @@ void Lobby::serverCommand(const ServerCommand & command) try
 		break;
 		break;
 		}
 		}
 
 
-	case CHAT:
+	case CHAT: {
 		protocolAssert(args.size() > 1);
 		protocolAssert(args.size() > 1);
 		QString msg;
 		QString msg;
 		for(int i = 1; i < args.size(); ++i)
 		for(int i = 1; i < args.size(); ++i)
 			msg += args[i];
 			msg += args[i];
 		chatMessage(args[0], msg);
 		chatMessage(args[0], msg);
 		break;
 		break;
+		}
+
+	default:
+		sysMessage("Unknown server command");
 	}
 	}
 
 
-	if(authentificationStatus == 2)
+	if(authentificationStatus == AuthStatus::ERROR)
 		socketLobby.disconnectServer();
 		socketLobby.disconnectServer();
 	else
 	else
-		authentificationStatus = 1;
+		authentificationStatus = AuthStatus::OK;
 }
 }
 catch(const ProtocolError & e)
 catch(const ProtocolError & e)
 {
 {
@@ -177,7 +236,7 @@ catch(const ProtocolError & e)
 
 
 void Lobby::onDisconnected()
 void Lobby::onDisconnected()
 {
 {
-	authentificationStatus = 0;
+	authentificationStatus = AuthStatus::NONE;
 	ui->stackedWidget->setCurrentWidget(ui->sessionsPage);
 	ui->stackedWidget->setCurrentWidget(ui->sessionsPage);
 	ui->connectButton->setChecked(false);
 	ui->connectButton->setChecked(false);
 }
 }
@@ -217,7 +276,7 @@ void Lobby::on_connectButton_toggled(bool checked)
 {
 {
 	if(checked)
 	if(checked)
 	{
 	{
-		authentificationStatus = 0;
+		authentificationStatus = AuthStatus::NONE;
 		username = ui->userEdit->text();
 		username = ui->userEdit->text();
 		const int connectionTimeout = settings["launcher"]["connectionTimeout"].Integer();
 		const int connectionTimeout = settings["launcher"]["connectionTimeout"].Integer();
 
 
@@ -241,7 +300,7 @@ void Lobby::on_connectButton_toggled(bool checked)
 
 
 void Lobby::on_newButton_clicked()
 void Lobby::on_newButton_clicked()
 {
 {
-	new LobbyRoomRequest(socketLobby, "", this);
+	new LobbyRoomRequest(socketLobby, "", buildModsMap(), this);
 }
 }
 
 
 void Lobby::on_joinButton_clicked()
 void Lobby::on_joinButton_clicked()
@@ -251,9 +310,9 @@ void Lobby::on_joinButton_clicked()
 	{
 	{
 		auto isPrivate = ui->sessionsTable->item(ui->sessionsTable->currentRow(), 2)->data(Qt::UserRole).toBool();
 		auto isPrivate = ui->sessionsTable->item(ui->sessionsTable->currentRow(), 2)->data(Qt::UserRole).toBool();
 		if(isPrivate)
 		if(isPrivate)
-			new LobbyRoomRequest(socketLobby, item->text(), this);
+			new LobbyRoomRequest(socketLobby, item->text(), buildModsMap(), this);
 		else
 		else
-			socketLobby.requestJoinSession(item->text(), "");
+			socketLobby.requestJoinSession(item->text(), "", buildModsMap());
 	}
 	}
 }
 }
 
 

+ 10 - 1
launcher/lobby/lobby_moc.h

@@ -42,8 +42,17 @@ private:
 	QString username;
 	QString username;
 	QStringList gameArgs;
 	QStringList gameArgs;
 
 
-	int authentificationStatus = 0;
+	enum AuthStatus
+	{
+		NONE, OK, ERROR
+	};
+
+	AuthStatus authentificationStatus = NONE;
 
 
 private:
 private:
+	QMap<QString, QString> buildModsMap() const;
+	bool isModAvailable(const QString & modName, const QString & modVersion) const;
+
+
 	void protocolAssert(bool);
 	void protocolAssert(bool);
 };
 };

+ 34 - 3
launcher/lobby/lobby_moc.ui

@@ -148,14 +148,34 @@
      </widget>
      </widget>
      <widget class="QWidget" name="roomPage">
      <widget class="QWidget" name="roomPage">
       <layout class="QGridLayout" name="gridLayout_3">
       <layout class="QGridLayout" name="gridLayout_3">
-       <item row="1" column="0">
+       <item row="4" column="0">
         <widget class="QPushButton" name="buttonLeave">
         <widget class="QPushButton" name="buttonLeave">
          <property name="text">
          <property name="text">
           <string>Leave</string>
           <string>Leave</string>
          </property>
          </property>
         </widget>
         </widget>
        </item>
        </item>
-       <item row="1" column="1">
+       <item row="3" column="0" colspan="2">
+        <widget class="QListWidget" name="modsList">
+         <property name="editTriggers">
+          <set>QAbstractItemView::NoEditTriggers</set>
+         </property>
+         <property name="selectionMode">
+          <enum>QAbstractItemView::NoSelection</enum>
+         </property>
+        </widget>
+       </item>
+       <item row="1" column="0" colspan="2">
+        <widget class="QListWidget" name="playersList">
+         <property name="editTriggers">
+          <set>QAbstractItemView::NoEditTriggers</set>
+         </property>
+         <property name="selectionMode">
+          <enum>QAbstractItemView::NoSelection</enum>
+         </property>
+        </widget>
+       </item>
+       <item row="4" column="1">
         <widget class="QPushButton" name="buttonReady">
         <widget class="QPushButton" name="buttonReady">
          <property name="text">
          <property name="text">
           <string>Ready</string>
           <string>Ready</string>
@@ -163,7 +183,18 @@
         </widget>
         </widget>
        </item>
        </item>
        <item row="0" column="0" colspan="2">
        <item row="0" column="0" colspan="2">
-        <widget class="QPlainTextEdit" name="roomChat"/>
+        <widget class="QLabel" name="label_3">
+         <property name="text">
+          <string>Players in the room</string>
+         </property>
+        </widget>
+       </item>
+       <item row="2" column="0">
+        <widget class="QLabel" name="label_5">
+         <property name="text">
+          <string>Mods mismatch</string>
+         </property>
+        </widget>
        </item>
        </item>
       </layout>
       </layout>
      </widget>
      </widget>

+ 5 - 4
launcher/lobby/lobbyroomrequest_moc.cpp

@@ -1,10 +1,11 @@
 #include "lobbyroomrequest_moc.h"
 #include "lobbyroomrequest_moc.h"
 #include "ui_lobbyroomrequest_moc.h"
 #include "ui_lobbyroomrequest_moc.h"
 
 
-LobbyRoomRequest::LobbyRoomRequest(SocketLobby & socket, const QString & room, QWidget *parent) :
+LobbyRoomRequest::LobbyRoomRequest(SocketLobby & socket, const QString & room, const QMap<QString, QString> & mods, QWidget *parent) :
 	QDialog(parent),
 	QDialog(parent),
 	ui(new Ui::LobbyRoomRequest),
 	ui(new Ui::LobbyRoomRequest),
-	socketLobby(socket)
+	socketLobby(socket),
+	mods(mods)
 {
 {
 	ui->setupUi(this);
 	ui->setupUi(this);
 	ui->nameEdit->setText(room);
 	ui->nameEdit->setText(room);
@@ -26,14 +27,14 @@ void LobbyRoomRequest::on_buttonBox_accepted()
 {
 {
 	if(ui->nameEdit->isReadOnly())
 	if(ui->nameEdit->isReadOnly())
 	{
 	{
-		socketLobby.requestJoinSession(ui->nameEdit->text(), ui->passwordEdit->text());
+		socketLobby.requestJoinSession(ui->nameEdit->text(), ui->passwordEdit->text(), mods);
 	}
 	}
 	else
 	else
 	{
 	{
 		if(!ui->nameEdit->text().isEmpty())
 		if(!ui->nameEdit->text().isEmpty())
 		{
 		{
 			int totalPlayers = ui->totalPlayers->currentIndex() + 2; //where 2 is a minimum amount of players
 			int totalPlayers = ui->totalPlayers->currentIndex() + 2; //where 2 is a minimum amount of players
-			socketLobby.requestNewSession(ui->nameEdit->text(), totalPlayers, ui->passwordEdit->text());
+			socketLobby.requestNewSession(ui->nameEdit->text(), totalPlayers, ui->passwordEdit->text(), mods);
 		}
 		}
 	}
 	}
 }
 }

+ 2 - 1
launcher/lobby/lobbyroomrequest_moc.h

@@ -13,7 +13,7 @@ class LobbyRoomRequest : public QDialog
 	Q_OBJECT
 	Q_OBJECT
 
 
 public:
 public:
-	explicit LobbyRoomRequest(SocketLobby & socket, const QString & room, QWidget *parent = nullptr);
+	explicit LobbyRoomRequest(SocketLobby & socket, const QString & room, const QMap<QString, QString> & mods, QWidget *parent = nullptr);
 	~LobbyRoomRequest();
 	~LobbyRoomRequest();
 
 
 private slots:
 private slots:
@@ -22,6 +22,7 @@ private slots:
 private:
 private:
 	Ui::LobbyRoomRequest *ui;
 	Ui::LobbyRoomRequest *ui;
 	SocketLobby & socketLobby;
 	SocketLobby & socketLobby;
+	QMap<QString, QString> mods;
 };
 };
 
 
 #endif // LOBBYROOMREQUEST_MOC_H
 #endif // LOBBYROOMREQUEST_MOC_H

+ 5 - 0
launcher/mainwindow_moc.cpp

@@ -116,3 +116,8 @@ void MainWindow::on_startGameButton_clicked()
 {
 {
 	startGame({});
 	startGame({});
 }
 }
+
+const CModList & MainWindow::getModList() const
+{
+	return ui->modlistView->getModList();
+}

+ 5 - 0
launcher/mainwindow_moc.h

@@ -19,6 +19,8 @@ const QString appName = "VCMI Launcher";
 }
 }
 
 
 class QTableWidgetItem;
 class QTableWidgetItem;
+class CModList;
+
 
 
 class MainWindow : public QMainWindow
 class MainWindow : public QMainWindow
 {
 {
@@ -31,6 +33,9 @@ private:
 public:
 public:
 	explicit MainWindow(QWidget * parent = 0);
 	explicit MainWindow(QWidget * parent = 0);
 	~MainWindow();
 	~MainWindow();
+
+	const CModList & getModList() const;
+
 	
 	
 public slots:
 public slots:
 	void on_startGameButton_clicked();
 	void on_startGameButton_clicked();