mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-28 08:48:48 +02:00
Support mod list
This commit is contained in:
parent
4527bd1a61
commit
05e4188908
@ -39,15 +39,15 @@ void SocketLobby::disconnectServer()
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -111,3 +111,13 @@ ServerCommand::ServerCommand(ProtocolConsts cmd, const QStringList & args):
|
||||
arguments(args)
|
||||
{
|
||||
}
|
||||
|
||||
QString prepareModsClientString(const QMap<QString, QString> & mods)
|
||||
{
|
||||
QStringList result;
|
||||
for(auto & mod : mods.keys())
|
||||
{
|
||||
result << mod + "&" + mods[mod];
|
||||
}
|
||||
return result.join(";");
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include <QTcpSocket>
|
||||
#include <QAbstractSocket>
|
||||
|
||||
const unsigned int ProtocolVersion = 1;
|
||||
const unsigned int ProtocolVersion = 2;
|
||||
const std::string ProtocolEncoding = "utf8";
|
||||
|
||||
class ProtocolError: public std::runtime_error
|
||||
@ -27,7 +27,7 @@ enum ProtocolConsts
|
||||
GREETING, USERNAME, MESSAGE, VERSION, CREATE, JOIN, LEAVE, READY,
|
||||
|
||||
//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
|
||||
@ -36,8 +36,8 @@ const QMap<ProtocolConsts, QString> ProtocolStrings
|
||||
{GREETING, "%1<GREETINGS>%2<VER>%3"}, //protocol_version byte, encoding bytes, encoding, name, version
|
||||
{USERNAME, "<USER>%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
|
||||
{READY, "<READY>%1"}, //session
|
||||
|
||||
@ -50,6 +50,7 @@ const QMap<ProtocolConsts, QString> ProtocolStrings
|
||||
{HOST, "HOST"}, //host_uuid:players_count
|
||||
{STATUS, "STATUS"}, //joined_players:player_name:is_ready
|
||||
{SRVERROR, "ERROR"},
|
||||
{MODS, "MODS"}, //amount:modname:modversion
|
||||
{CHAT, "MSG"} //username:message
|
||||
};
|
||||
|
||||
@ -69,8 +70,8 @@ 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);
|
||||
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 requestReadySession(const QString & session);
|
||||
|
||||
@ -93,5 +94,6 @@ private:
|
||||
QTcpSocket *socket;
|
||||
bool isConnected = false;
|
||||
QString username;
|
||||
|
||||
};
|
||||
|
||||
QString prepareModsClientString(const QMap<QString, QString> & mods);
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "ui_lobby_moc.h"
|
||||
#include "lobbyroomrequest_moc.h"
|
||||
#include "../mainwindow_moc.h"
|
||||
#include "../modManager/cmodlist.h"
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
|
||||
Lobby::Lobby(QWidget *parent) :
|
||||
@ -27,11 +28,35 @@ Lobby::~Lobby()
|
||||
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
|
||||
{
|
||||
//initialize variables outside of switch block
|
||||
const QString statusPlaceholder("%1 %2\n");
|
||||
QString resText;
|
||||
const auto & args = command.arguments;
|
||||
int amount, tagPoint;
|
||||
QString joinStr;
|
||||
@ -40,8 +65,8 @@ void Lobby::serverCommand(const ServerCommand & command) try
|
||||
case SRVERROR:
|
||||
protocolAssert(args.size());
|
||||
chatMessage("System error", args[0], true);
|
||||
if(authentificationStatus == 0)
|
||||
authentificationStatus = 2;
|
||||
if(authentificationStatus == AuthStatus::NONE)
|
||||
authentificationStatus = AuthStatus::ERROR;
|
||||
break;
|
||||
|
||||
case CREATED:
|
||||
@ -98,19 +123,49 @@ void Lobby::serverCommand(const ServerCommand & command) try
|
||||
}
|
||||
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:
|
||||
protocolAssert(args.size() > 0);
|
||||
amount = args[0].toInt();
|
||||
protocolAssert(amount * 2 == (args.size() - 1));
|
||||
|
||||
tagPoint = 1;
|
||||
ui->roomChat->clear();
|
||||
resText.clear();
|
||||
ui->playersList->clear();
|
||||
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;
|
||||
|
||||
case START: {
|
||||
@ -132,19 +187,23 @@ void Lobby::serverCommand(const ServerCommand & command) try
|
||||
break;
|
||||
}
|
||||
|
||||
case CHAT:
|
||||
case CHAT: {
|
||||
protocolAssert(args.size() > 1);
|
||||
QString msg;
|
||||
for(int i = 1; i < args.size(); ++i)
|
||||
msg += args[i];
|
||||
chatMessage(args[0], msg);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
sysMessage("Unknown server command");
|
||||
}
|
||||
|
||||
if(authentificationStatus == 2)
|
||||
if(authentificationStatus == AuthStatus::ERROR)
|
||||
socketLobby.disconnectServer();
|
||||
else
|
||||
authentificationStatus = 1;
|
||||
authentificationStatus = AuthStatus::OK;
|
||||
}
|
||||
catch(const ProtocolError & e)
|
||||
{
|
||||
@ -177,7 +236,7 @@ catch(const ProtocolError & e)
|
||||
|
||||
void Lobby::onDisconnected()
|
||||
{
|
||||
authentificationStatus = 0;
|
||||
authentificationStatus = AuthStatus::NONE;
|
||||
ui->stackedWidget->setCurrentWidget(ui->sessionsPage);
|
||||
ui->connectButton->setChecked(false);
|
||||
}
|
||||
@ -217,7 +276,7 @@ void Lobby::on_connectButton_toggled(bool checked)
|
||||
{
|
||||
if(checked)
|
||||
{
|
||||
authentificationStatus = 0;
|
||||
authentificationStatus = AuthStatus::NONE;
|
||||
username = ui->userEdit->text();
|
||||
const int connectionTimeout = settings["launcher"]["connectionTimeout"].Integer();
|
||||
|
||||
@ -241,7 +300,7 @@ void Lobby::on_connectButton_toggled(bool checked)
|
||||
|
||||
void Lobby::on_newButton_clicked()
|
||||
{
|
||||
new LobbyRoomRequest(socketLobby, "", this);
|
||||
new LobbyRoomRequest(socketLobby, "", buildModsMap(), this);
|
||||
}
|
||||
|
||||
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();
|
||||
if(isPrivate)
|
||||
new LobbyRoomRequest(socketLobby, item->text(), this);
|
||||
new LobbyRoomRequest(socketLobby, item->text(), buildModsMap(), this);
|
||||
else
|
||||
socketLobby.requestJoinSession(item->text(), "");
|
||||
socketLobby.requestJoinSession(item->text(), "", buildModsMap());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,8 +42,17 @@ private:
|
||||
QString username;
|
||||
QStringList gameArgs;
|
||||
|
||||
int authentificationStatus = 0;
|
||||
enum AuthStatus
|
||||
{
|
||||
NONE, OK, ERROR
|
||||
};
|
||||
|
||||
AuthStatus authentificationStatus = NONE;
|
||||
|
||||
private:
|
||||
QMap<QString, QString> buildModsMap() const;
|
||||
bool isModAvailable(const QString & modName, const QString & modVersion) const;
|
||||
|
||||
|
||||
void protocolAssert(bool);
|
||||
};
|
||||
|
@ -148,14 +148,34 @@
|
||||
</widget>
|
||||
<widget class="QWidget" name="roomPage">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="1" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QPushButton" name="buttonLeave">
|
||||
<property name="text">
|
||||
<string>Leave</string>
|
||||
</property>
|
||||
</widget>
|
||||
</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">
|
||||
<property name="text">
|
||||
<string>Ready</string>
|
||||
@ -163,7 +183,18 @@
|
||||
</widget>
|
||||
</item>
|
||||
<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>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -1,10 +1,11 @@
|
||||
#include "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),
|
||||
ui(new Ui::LobbyRoomRequest),
|
||||
socketLobby(socket)
|
||||
socketLobby(socket),
|
||||
mods(mods)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->nameEdit->setText(room);
|
||||
@ -26,14 +27,14 @@ void LobbyRoomRequest::on_buttonBox_accepted()
|
||||
{
|
||||
if(ui->nameEdit->isReadOnly())
|
||||
{
|
||||
socketLobby.requestJoinSession(ui->nameEdit->text(), ui->passwordEdit->text());
|
||||
socketLobby.requestJoinSession(ui->nameEdit->text(), ui->passwordEdit->text(), mods);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!ui->nameEdit->text().isEmpty())
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ class LobbyRoomRequest : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
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();
|
||||
|
||||
private slots:
|
||||
@ -22,6 +22,7 @@ private slots:
|
||||
private:
|
||||
Ui::LobbyRoomRequest *ui;
|
||||
SocketLobby & socketLobby;
|
||||
QMap<QString, QString> mods;
|
||||
};
|
||||
|
||||
#endif // LOBBYROOMREQUEST_MOC_H
|
||||
|
@ -116,3 +116,8 @@ void MainWindow::on_startGameButton_clicked()
|
||||
{
|
||||
startGame({});
|
||||
}
|
||||
|
||||
const CModList & MainWindow::getModList() const
|
||||
{
|
||||
return ui->modlistView->getModList();
|
||||
}
|
||||
|
@ -19,6 +19,8 @@ const QString appName = "VCMI Launcher";
|
||||
}
|
||||
|
||||
class QTableWidgetItem;
|
||||
class CModList;
|
||||
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
@ -31,6 +33,9 @@ private:
|
||||
public:
|
||||
explicit MainWindow(QWidget * parent = 0);
|
||||
~MainWindow();
|
||||
|
||||
const CModList & getModList() const;
|
||||
|
||||
|
||||
public slots:
|
||||
void on_startGameButton_clicked();
|
||||
|
Loading…
Reference in New Issue
Block a user