mirror of
https://github.com/vcmi/vcmi.git
synced 2025-06-15 00:05:02 +02:00
Automatic mod conflict resolution
This commit is contained in:
@ -134,6 +134,7 @@ void Lobby::serverCommand(const ServerCommand & command) try
|
|||||||
|
|
||||||
if(args[1] == username)
|
if(args[1] == username)
|
||||||
{
|
{
|
||||||
|
hostModsMap.clear();
|
||||||
ui->buttonReady->setText("Ready");
|
ui->buttonReady->setText("Ready");
|
||||||
ui->optNewGame->setChecked(true);
|
ui->optNewGame->setChecked(true);
|
||||||
sysMessage(joinStr.arg("you", args[0]));
|
sysMessage(joinStr.arg("you", args[0]));
|
||||||
@ -155,33 +156,15 @@ void Lobby::serverCommand(const ServerCommand & command) try
|
|||||||
protocolAssert(amount * 2 == (args.size() - 1));
|
protocolAssert(amount * 2 == (args.size() - 1));
|
||||||
|
|
||||||
tagPoint = 1;
|
tagPoint = 1;
|
||||||
ui->modsList->clear();
|
|
||||||
auto enabledMods = buildModsMap();
|
|
||||||
for(int i = 0; i < amount; ++i, tagPoint += 2)
|
for(int i = 0; i < amount; ++i, tagPoint += 2)
|
||||||
{
|
hostModsMap[args[tagPoint]] = args[tagPoint + 1];
|
||||||
if(enabledMods.contains(args[tagPoint]))
|
|
||||||
{
|
updateMods();
|
||||||
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CLIENTMODS: {
|
case CLIENTMODS: {
|
||||||
protocolAssert(args.size() > 1);
|
protocolAssert(args.size() >= 1);
|
||||||
amount = args[1].toInt();
|
amount = args[1].toInt();
|
||||||
protocolAssert(amount * 2 == (args.size() - 2));
|
protocolAssert(amount * 2 == (args.size() - 2));
|
||||||
|
|
||||||
@ -398,10 +381,87 @@ void Lobby::on_connectButton_toggled(bool checked)
|
|||||||
ui->serverEdit->setEnabled(true);
|
ui->serverEdit->setEnabled(true);
|
||||||
ui->userEdit->setEnabled(true);
|
ui->userEdit->setEnabled(true);
|
||||||
ui->listUsers->clear();
|
ui->listUsers->clear();
|
||||||
|
hostModsMap.clear();
|
||||||
|
updateMods();
|
||||||
socketLobby.disconnectServer();
|
socketLobby.disconnectServer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Lobby::updateMods()
|
||||||
|
{
|
||||||
|
ui->modsList->clear();
|
||||||
|
if(hostModsMap.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto enabledMods = buildModsMap();
|
||||||
|
for(auto & mod : hostModsMap.keys())
|
||||||
|
{
|
||||||
|
auto & modValue = hostModsMap[mod];
|
||||||
|
auto modName = QString("%1 (v%2)").arg(mod, modValue);
|
||||||
|
//first - mod name
|
||||||
|
//second.first - should mod be enabled
|
||||||
|
//second.second - is possible to resolve
|
||||||
|
QMap<QString, QVariant> modData;
|
||||||
|
QList<QVariant> modDataVal;
|
||||||
|
if(enabledMods.contains(mod))
|
||||||
|
{
|
||||||
|
if(enabledMods[mod] == modValue)
|
||||||
|
enabledMods.remove(mod); //mod fully matches, remove from list
|
||||||
|
else
|
||||||
|
{
|
||||||
|
modDataVal.append(true);
|
||||||
|
modDataVal.append(false);
|
||||||
|
modData[mod] = modDataVal;
|
||||||
|
auto * lw = new QListWidgetItem(QIcon("icons:mod-update.png"), modName); //mod version mismatch
|
||||||
|
lw->setData(Qt::UserRole, modData);
|
||||||
|
ui->modsList->addItem(lw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(isModAvailable(mod, modValue))
|
||||||
|
{
|
||||||
|
modDataVal.append(true);
|
||||||
|
modDataVal.append(true);
|
||||||
|
modData[mod] = modDataVal;
|
||||||
|
auto * lw = new QListWidgetItem(QIcon("icons:mod-enabled.png"), modName); //mod available and needs to be enabled
|
||||||
|
lw->setData(Qt::UserRole, modData);
|
||||||
|
ui->modsList->addItem(lw);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
modDataVal.append(true);
|
||||||
|
modDataVal.append(false);
|
||||||
|
modData[mod] = modDataVal;
|
||||||
|
auto * lw = new QListWidgetItem(QIcon("icons:mod-delete.png"), modName); //mod is not available and needs to be installed
|
||||||
|
lw->setData(Qt::UserRole, modData);
|
||||||
|
ui->modsList->addItem(lw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(auto & remainMod : enabledMods.keys())
|
||||||
|
{
|
||||||
|
//first - mod name
|
||||||
|
//second.first - should mod be enabled
|
||||||
|
//second.second - is possible to resolve
|
||||||
|
QMap<QString, QVariant> modData;
|
||||||
|
QList<QVariant> modDataVal;
|
||||||
|
modDataVal.append(false);
|
||||||
|
modDataVal.append(true);
|
||||||
|
modData[remainMod] = modDataVal;
|
||||||
|
auto modName = QString("%1 (v%2)").arg(remainMod, enabledMods[remainMod]);
|
||||||
|
auto * lw = new QListWidgetItem(QIcon("icons:mod-disabled.png"), modName); //mod needs to be disabled
|
||||||
|
lw->setData(Qt::UserRole, modData);
|
||||||
|
ui->modsList->addItem(lw);
|
||||||
|
}
|
||||||
|
if(!ui->modsList->count())
|
||||||
|
{
|
||||||
|
ui->buttonResolve->setEnabled(false);
|
||||||
|
ui->modsList->addItem("No issues detected");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui->buttonResolve->setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Lobby::on_newButton_clicked()
|
void Lobby::on_newButton_clicked()
|
||||||
{
|
{
|
||||||
new LobbyRoomRequest(socketLobby, "", buildModsMap(), this);
|
new LobbyRoomRequest(socketLobby, "", buildModsMap(), this);
|
||||||
@ -456,7 +516,31 @@ void Lobby::on_kickButton_clicked()
|
|||||||
|
|
||||||
void Lobby::on_buttonResolve_clicked()
|
void Lobby::on_buttonResolve_clicked()
|
||||||
{
|
{
|
||||||
//TODO: auto-resolve mods conflicts
|
QStringList toEnableList, toDisableList;
|
||||||
|
for(auto * item : ui->modsList->selectedItems())
|
||||||
|
{
|
||||||
|
auto data = item->data(Qt::UserRole);
|
||||||
|
if(data.isNull())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto modData = data.toMap();
|
||||||
|
assert(modData.size() == 1);
|
||||||
|
auto modDataVal = modData.begin()->toList();
|
||||||
|
assert(modDataVal.size() == 2);
|
||||||
|
if(!modDataVal[1].toBool())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(modDataVal[0].toBool())
|
||||||
|
toEnableList << modData.begin().key();
|
||||||
|
else
|
||||||
|
toDisableList << modData.begin().key();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto & mod : toDisableList)
|
||||||
|
emit disableMod(mod);
|
||||||
|
for(auto & mod : toEnableList)
|
||||||
|
emit enableMod(mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lobby::on_optNewGame_toggled(bool checked)
|
void Lobby::on_optNewGame_toggled(bool checked)
|
||||||
|
@ -23,6 +23,14 @@ public:
|
|||||||
explicit Lobby(QWidget *parent = nullptr);
|
explicit Lobby(QWidget *parent = nullptr);
|
||||||
~Lobby();
|
~Lobby();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void enableMod(QString mod);
|
||||||
|
void disableMod(QString mod);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void updateMods();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_messageEdit_returnPressed();
|
void on_messageEdit_returnPressed();
|
||||||
|
|
||||||
@ -66,6 +74,7 @@ private:
|
|||||||
QString session;
|
QString session;
|
||||||
QString username;
|
QString username;
|
||||||
QStringList gameArgs;
|
QStringList gameArgs;
|
||||||
|
QMap<QString, QString> hostModsMap;
|
||||||
|
|
||||||
enum AuthStatus
|
enum AuthStatus
|
||||||
{
|
{
|
||||||
|
@ -54,6 +54,10 @@ MainWindow::MainWindow(QWidget * parent)
|
|||||||
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
connect(ui->lobbyView, &Lobby::enableMod, ui->modlistView, &CModListView::enableModByName);
|
||||||
|
connect(ui->lobbyView, &Lobby::disableMod, ui->modlistView, &CModListView::disableModByName);
|
||||||
|
connect(ui->modlistView, &CModListView::modsChanged, ui->lobbyView, &Lobby::updateMods);
|
||||||
|
|
||||||
//load window settings
|
//load window settings
|
||||||
QSettings s(Ui::teamName, Ui::appName);
|
QSettings s(Ui::teamName, Ui::appName);
|
||||||
|
|
||||||
|
@ -497,6 +497,13 @@ void CModListView::on_enableButton_clicked()
|
|||||||
{
|
{
|
||||||
QString modName = ui->allModsView->currentIndex().data(ModRoles::ModNameRole).toString();
|
QString modName = ui->allModsView->currentIndex().data(ModRoles::ModNameRole).toString();
|
||||||
|
|
||||||
|
enableModByName(modName);
|
||||||
|
|
||||||
|
checkManagerErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CModListView::enableModByName(QString modName)
|
||||||
|
{
|
||||||
assert(findBlockingMods(modName).empty());
|
assert(findBlockingMods(modName).empty());
|
||||||
assert(findInvalidDependencies(modName).empty());
|
assert(findInvalidDependencies(modName).empty());
|
||||||
|
|
||||||
@ -505,17 +512,24 @@ void CModListView::on_enableButton_clicked()
|
|||||||
if(modModel->getMod(name).isDisabled())
|
if(modModel->getMod(name).isDisabled())
|
||||||
manager->enableMod(name);
|
manager->enableMod(name);
|
||||||
}
|
}
|
||||||
checkManagerErrors();
|
emit modsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CModListView::on_disableButton_clicked()
|
void CModListView::on_disableButton_clicked()
|
||||||
{
|
{
|
||||||
QString modName = ui->allModsView->currentIndex().data(ModRoles::ModNameRole).toString();
|
QString modName = ui->allModsView->currentIndex().data(ModRoles::ModNameRole).toString();
|
||||||
|
|
||||||
|
disableModByName(modName);
|
||||||
|
|
||||||
|
checkManagerErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CModListView::disableModByName(QString modName)
|
||||||
|
{
|
||||||
if(modModel->hasMod(modName) && modModel->getMod(modName).isEnabled())
|
if(modModel->hasMod(modName) && modModel->getMod(modName).isEnabled())
|
||||||
manager->disableMod(modName);
|
manager->disableMod(modName);
|
||||||
|
|
||||||
checkManagerErrors();
|
emit modsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CModListView::on_updateButton_clicked()
|
void CModListView::on_updateButton_clicked()
|
||||||
@ -544,6 +558,8 @@ void CModListView::on_uninstallButton_clicked()
|
|||||||
manager->disableMod(modName);
|
manager->disableMod(modName);
|
||||||
manager->uninstallMod(modName);
|
manager->uninstallMod(modName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit modsChanged();
|
||||||
checkManagerErrors();
|
checkManagerErrors();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -631,6 +647,8 @@ void CModListView::downloadFinished(QStringList savedFiles, QStringList failedFi
|
|||||||
|
|
||||||
if(doInstallFiles)
|
if(doInstallFiles)
|
||||||
installFiles(savedFiles);
|
installFiles(savedFiles);
|
||||||
|
|
||||||
|
emit modsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CModListView::hideProgressBar()
|
void CModListView::hideProgressBar()
|
||||||
|
@ -67,6 +67,8 @@ class CModListView : public QWidget
|
|||||||
signals:
|
signals:
|
||||||
void extraResolutionsEnabledChanged(bool enabled);
|
void extraResolutionsEnabledChanged(bool enabled);
|
||||||
|
|
||||||
|
void modsChanged();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CModListView(QWidget * parent = 0);
|
explicit CModListView(QWidget * parent = 0);
|
||||||
~CModListView();
|
~CModListView();
|
||||||
@ -83,6 +85,10 @@ public:
|
|||||||
|
|
||||||
const CModList & getModList() const;
|
const CModList & getModList() const;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void enableModByName(QString modName);
|
||||||
|
void disableModByName(QString modName);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void dataChanged(const QModelIndex & topleft, const QModelIndex & bottomRight);
|
void dataChanged(const QModelIndex & topleft, const QModelIndex & bottomRight);
|
||||||
void modSelected(const QModelIndex & current, const QModelIndex & previous);
|
void modSelected(const QModelIndex & current, const QModelIndex & previous);
|
||||||
|
Reference in New Issue
Block a user