From 9e2bcffc32157b99a2d7364b869a4423ba827a32 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 28 Nov 2015 14:53:32 +0000 Subject: Reworked startup considerably so now no longer dependant on GameInfo Did some const correctness to the "managed_game" property as you shouldn't really be altering the plugin details whilst MO is running --- src/directoryrefresher.cpp | 2 +- src/loadmechanism.cpp | 14 ++-- src/main.cpp | 204 ++++++++++++++++++++++++++++++--------------- src/modinfo.cpp | 6 +- src/organizercore.cpp | 18 ++-- src/organizercore.h | 5 +- src/settingsdialog.cpp | 2 +- src/shared/fallout3info.h | 2 - src/shared/falloutnvinfo.h | 2 - src/shared/gameinfo.h | 7 +- src/shared/oblivioninfo.h | 2 - src/shared/skyriminfo.h | 2 - 12 files changed, 156 insertions(+), 110 deletions(-) (limited to 'src') diff --git a/src/directoryrefresher.cpp b/src/directoryrefresher.cpp index 4eac4103..f50a717e 100644 --- a/src/directoryrefresher.cpp +++ b/src/directoryrefresher.cpp @@ -144,7 +144,7 @@ void DirectoryRefresher::refresh() m_DirectoryStructure = new DirectoryEntry(L"data", nullptr, 0); - IPluginGame *game = qApp->property("managed_game").value(); + IPluginGame const *game = qApp->property("managed_game").value(); std::wstring dataDirectory = QDir::toNativeSeparators(game->dataDirectory().absolutePath()).toStdWString(); m_DirectoryStructure->addFromOrigin(L"data", dataDirectory, 0); diff --git a/src/loadmechanism.cpp b/src/loadmechanism.cpp index 0d95c51c..521473b0 100644 --- a/src/loadmechanism.cpp +++ b/src/loadmechanism.cpp @@ -65,7 +65,7 @@ void LoadMechanism::removeHintFile(QDir &targetDirectory) bool LoadMechanism::isDirectLoadingSupported() { //FIXME: Seriously? isn't there a 'do i need steam' thing? - IPluginGame *game = qApp->property("managed_game").value(); + IPluginGame const *game = qApp->property("managed_game").value(); if (game->gameName().compare("oblivion", Qt::CaseInsensitive) == 0) { // oblivion can be loaded directly if it's not the steam variant return !game->gameDirectory().exists("steam_api.dll"); @@ -77,7 +77,7 @@ bool LoadMechanism::isDirectLoadingSupported() bool LoadMechanism::isScriptExtenderSupported() { - IPluginGame *game = qApp->property("managed_game").value(); + IPluginGame const *game = qApp->property("managed_game").value(); ScriptExtender *extender = game->feature(); // test if there even is an extender for the managed game and if so whether it's installed @@ -93,7 +93,7 @@ bool LoadMechanism::isProxyDLLSupported() // plus: the proxy dll hasn't been working for at least the whole 1.12.x versions of MO and // noone reported it so why maintain an unused feature? return false; -/* IPluginGame *game = qApp->property("managed_game").value(); +/* IPluginGame const *game = qApp->property("managed_game").value(); return game->gameDirectory().exists(QString::fromStdWString(AppConfig::proxyDLLTarget()));*/ } @@ -125,7 +125,7 @@ bool LoadMechanism::hashIdentical(const QString &fileNameLHS, const QString &fil void LoadMechanism::deactivateScriptExtender() { try { - IPluginGame *game = qApp->property("managed_game").value(); + IPluginGame const *game = qApp->property("managed_game").value(); ScriptExtender *extender = game->feature(); if (extender == nullptr) { throw MyException(QObject::tr("game doesn't support a script extender")); @@ -151,7 +151,7 @@ void LoadMechanism::deactivateScriptExtender() void LoadMechanism::deactivateProxyDLL() { try { - IPluginGame *game = qApp->property("managed_game").value(); + IPluginGame const *game = qApp->property("managed_game").value(); QString targetPath = game->gameDirectory().absoluteFilePath(QString::fromStdWString(AppConfig::proxyDLLTarget())); @@ -180,7 +180,7 @@ void LoadMechanism::deactivateProxyDLL() void LoadMechanism::activateScriptExtender() { try { - IPluginGame *game = qApp->property("managed_game").value(); + IPluginGame const *game = qApp->property("managed_game").value(); ScriptExtender *extender = game->feature(); if (extender == nullptr) { throw MyException(QObject::tr("game doesn't support a script extender")); @@ -220,7 +220,7 @@ void LoadMechanism::activateScriptExtender() void LoadMechanism::activateProxyDLL() { try { - IPluginGame *game = qApp->property("managed_game").value(); + IPluginGame const *game = qApp->property("managed_game").value(); QString targetPath = game->gameDirectory().absoluteFilePath(QString::fromStdWString(AppConfig::proxyDLLTarget())); diff --git a/src/main.cpp b/src/main.cpp index 72a63dc6..78145a74 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -330,6 +330,122 @@ QString determineProfile(QStringList &arguments, const QSettings &settings) return selectedProfileName; } +MOBase::IPluginGame *selectGame(QSettings &settings, QDir const &gamePath, MOBase::IPluginGame *game) +{ + settings.setValue("gameName", game->gameName()); + if (gamePath == game->gameDirectory()) { + settings.remove("gamePath"); + } else { + QString gameDir = gamePath.absolutePath(); + game->setGamePath(gameDir); + settings.setValue("gamePath", QDir::toNativeSeparators(gameDir).toUtf8().constData()); + } + return game; //Woot +} + + +MOBase::IPluginGame *determineCurrentGame(QString const &moPath, QSettings &settings, PluginContainer const &plugins) +{ + //Determine what game we are running where. Be very paranoid in case the + //user has done something odd. + //If the game name has been set up, use that. + QString gameName = settings.value("gameName", "").toString(); + if (!gameName.isEmpty()) { + MOBase::IPluginGame *game = plugins.managedGame(gameName); + if (game == nullptr) { + reportError(QObject::tr("Plugin to handle %1 no longer installed").arg(gameName)); + return nullptr; + } + QString gamePath = QString::fromUtf8(settings.value("gamePath", "").toByteArray()); + if (gamePath == "") { + gamePath = game->gameDirectory().absolutePath(); + } + QDir gameDir(gamePath); + if (game->looksValid(gameDir)) { + return selectGame(settings, gameDir, game); + } + } + + //gameName wasn't set, or otherwise can't be found. Try looking through all + //the plugins using the gamePath + QString gamePath = QString::fromUtf8(settings.value("gamePath", "").toByteArray()); + if (!gamePath.isEmpty()) { + QDir gameDir(gamePath); + //Look to see if one of the installed games binary file exists in the current + //game directory. + for (IPluginGame * const game : plugins.plugins()) { + if (game->looksValid(gameDir)) { + return selectGame(settings, gameDir, game); + } + } + } + + //OK, we are in a new setup or existing info is useless. + //See if MO has been installed inside a game directory + for (IPluginGame * const game : plugins.plugins()) { + if (game->isInstalled() && moPath.startsWith(game->gameDirectory().absolutePath())) { + //Found it. + return selectGame(settings, game->gameDirectory(), game); + } + } + + //Try walking up the directory tree to see if MO has been installed inside a game + { + QDir gameDir(moPath); + do { + //Look to see if one of the installed games binary file exists in the current + //directory. + for (IPluginGame * const game : plugins.plugins()) { + if (game->looksValid(gameDir)) { + return selectGame(settings, gameDir, game); + } + } + //OK, chop off the last directory and try again + } while (gameDir.cdUp()); + } + + //Then try a selection dialogue. + if (!gamePath.isEmpty() || !gameName.isEmpty()) { + reportError(QObject::tr("Could not use configuration settings for game \"%1\", path \"%2\"."). + arg(gameName).arg(gamePath)); + } + + SelectionDialog selection(QObject::tr("Please select the game to manage"), nullptr, QSize(32, 32)); + + for (IPluginGame *game : plugins.plugins()) { + if (game->isInstalled()) { + QString path = game->gameDirectory().absolutePath(); + selection.addChoice(game->gameIcon(), game->gameName(), path, QVariant::fromValue(game)); + } + } + + selection.addChoice(QString("Browse..."), QString(), QVariant::fromValue(static_cast(nullptr))); + + while (selection.exec() != QDialog::Rejected) { + IPluginGame * game = selection.getChoiceData().value(); + if (game != nullptr) { + return selectGame(settings, game->gameDirectory(), game); + } + + gamePath = QFileDialog::getExistingDirectory( + nullptr, QObject::tr("Please select the game to manage"), QString(), + QFileDialog::ShowDirsOnly); + + if (!gamePath.isEmpty()) { + QDir gameDir(gamePath); + for (IPluginGame * const game : plugins.plugins()) { + if (game->looksValid(gameDir)) { + return selectGame(settings, gameDir, game); + } + } + reportError(QObject::tr("No game identified in \"%1\". The directory is required to contain " + "the game binary and its launcher.").arg(gamePath)); + } + } + + return nullptr; +} + int main(int argc, char *argv[]) { MOApplication application(argc, argv); @@ -443,86 +559,36 @@ int main(int argc, char *argv[]) PluginContainer pluginContainer(&organizer); pluginContainer.loadPlugins(); - QString gamePath = QString::fromUtf8(settings.value("gamePath", "").toByteArray()); - bool done = false; - while (!done) { - if (!GameInfo::init(ToWString(application.applicationDirPath()), ToWString(QDir::toNativeSeparators(gamePath)))) { - if (!gamePath.isEmpty()) { - reportError(QObject::tr("No game identified in \"%1\". The directory is required to contain " - "the game binary and its launcher.").arg(gamePath)); - } - SelectionDialog selection(QObject::tr("Please select the game to manage"), nullptr, QSize(32, 32)); - - for (const IPluginGame * const game : pluginContainer.plugins()) { - if (game->isInstalled()) { - QString path = game->gameDirectory().absolutePath(); - selection.addChoice(game->gameIcon(), game->gameName(), path, path); - } - } - - selection.addChoice(QString("Browse..."), QString(), QString()); - - if (selection.exec() == QDialog::Rejected) { - gamePath = ""; - done = true; - } else { - gamePath = QDir::cleanPath(selection.getChoiceData().toString()); - if (gamePath.isEmpty()) { - gamePath = QFileDialog::getExistingDirectory( - nullptr, QObject::tr("Please select the game to manage"), QString(), - QFileDialog::ShowDirsOnly); - qDebug() << "manually selected path " << gamePath; - } - } - } else { - done = true; - gamePath = ToQString(GameInfo::instance().getGameDirectory()); - } - } - - if (gamePath.isEmpty()) { - // game not found and user canceled - return -1; - } else if (gamePath.length() != 0) { - // user selected a folder and game was initialised with it - qDebug("game path: %s", qPrintable(gamePath)); - settings.setValue("gamePath", gamePath.toUtf8().constData()); + MOBase::IPluginGame *game = determineCurrentGame(application.applicationDirPath(), settings, pluginContainer); + if (game == nullptr) { + return 1; } - organizer.setManagedGame(ToQString(GameInfo::instance().getGameName()), gamePath); + organizer.setManagedGame(game); organizer.createDefaultProfile(); - if (pluginContainer.managedGame(ToQString(GameInfo::instance().getGameName())) == nullptr) { - reportError(QObject::tr("Plugin to handle %1 not installed").arg(ToQString(GameInfo::instance().getGameName()))); - return 1; - } - - //This is probably wrong too - { - IPluginGame *game = organizer.managedGameForUpdate(); - - if (!settings.contains("game_edition")) { - QStringList editions = game->gameVariants(); - if (editions.size() > 1) { - SelectionDialog selection(QObject::tr("Please select the game edition you have (MO can't start the game correctly if this is set incorrectly!)"), nullptr); - int index = 0; - for (const QString &edition : editions) { - selection.addChoice(edition, "", index++); - } - if (selection.exec() == QDialog::Rejected) { - return -1; - } else { - settings.setValue("game_edition", selection.getChoiceString()); - } + //See the pragma - we apparently don't use this so not sure why we check it + if (!settings.contains("game_edition")) { + QStringList editions = game->gameVariants(); + if (editions.size() > 1) { + SelectionDialog selection(QObject::tr("Please select the game edition you have (MO can't start the game correctly if this is set incorrectly!)"), nullptr); + int index = 0; + for (const QString &edition : editions) { + selection.addChoice(edition, "", index++); + } + if (selection.exec() == QDialog::Rejected) { + return -1; + } else { + settings.setValue("game_edition", selection.getChoiceString()); } } - game->setGameVariant(settings.value("game_edition").toString()); } + game->setGameVariant(settings.value("game_edition").toString()); #pragma message("edition isn't used?") - qDebug("managing game at %s", qPrintable(QDir::toNativeSeparators(gamePath))); + qDebug("managing game at %s", qPrintable(QDir::toNativeSeparators(game->gameDirectory().absolutePath()))); organizer.updateExecutablesList(settings); diff --git a/src/modinfo.cpp b/src/modinfo.cpp index ef195bea..03ab9a95 100644 --- a/src/modinfo.cpp +++ b/src/modinfo.cpp @@ -290,7 +290,7 @@ int ModInfo::checkAllForUpdate(QObject *receiver) std::vector modIDs; //I ought to store this, it's used elsewhere - IPluginGame *game = qApp->property("managed_game").value(); + IPluginGame const *game = qApp->property("managed_game").value(); modIDs.push_back(game->getNexusModOrganizerID()); @@ -935,7 +935,7 @@ std::vector ModInfoRegular::getContents() const m_CachedContent.push_back(CONTENT_BSA); } - ScriptExtender *extender = qApp->property("managed_game").value()->feature(); + ScriptExtender *extender = qApp->property("managed_game").value()->feature(); if (extender != nullptr) { QString sePluginPath = extender->name() + "/plugins"; @@ -1137,7 +1137,7 @@ QDateTime ModInfoForeign::creationTime() const QString ModInfoForeign::absolutePath() const { //I ought to store this, it's used elsewhere - IPluginGame *game = qApp->property("managed_game").value(); + IPluginGame const *game = qApp->property("managed_game").value(); return game->dataDirectory().absolutePath(); } diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 042a9f1e..06a6dba4 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -422,15 +422,12 @@ void OrganizerCore::disconnectPlugins() m_PluginContainer = nullptr; } -void OrganizerCore::setManagedGame(const QString &gameName, const QString &gamePath) +void OrganizerCore::setManagedGame(MOBase::IPluginGame const *game) { - m_GameName = gameName; - if (m_PluginContainer != nullptr) { - m_GamePlugin = m_PluginContainer->managedGame(m_GameName); - m_GamePlugin->setGamePath(gamePath); - qApp->setProperty("managed_game", QVariant::fromValue(m_GamePlugin)); - emit managedGameChanged(m_GamePlugin); - } + m_GameName = game->gameName(); + m_GamePlugin = game; + qApp->setProperty("managed_game", QVariant::fromValue(m_GamePlugin)); + emit managedGameChanged(m_GamePlugin); } Settings &OrganizerCore::settings() @@ -1327,11 +1324,6 @@ IPluginGame const *OrganizerCore::managedGame() const return m_GamePlugin; } -IPluginGame *OrganizerCore::managedGameForUpdate() const -{ - return m_GamePlugin; -} - std::vector OrganizerCore::enabledArchives() { std::vector result; diff --git a/src/organizercore.h b/src/organizercore.h index c206e5e7..5cfbaca4 100644 --- a/src/organizercore.h +++ b/src/organizercore.h @@ -73,7 +73,7 @@ public: void connectPlugins(PluginContainer *container); void disconnectPlugins(); - void setManagedGame(const QString &gameName, const QString &gamePath); + void setManagedGame(const MOBase::IPluginGame *game); void updateExecutablesList(QSettings &settings); @@ -100,7 +100,6 @@ public: PluginListSortProxy *createPluginListProxyModel(); MOBase::IPluginGame const *managedGame() const; - MOBase::IPluginGame *managedGameForUpdate() const; bool isArchivesInit() const { return m_ArchivesInit; } @@ -234,7 +233,7 @@ private: IUserInterface *m_UserInterface; PluginContainer *m_PluginContainer; QString m_GameName; - MOBase::IPluginGame *m_GamePlugin; + MOBase::IPluginGame const *m_GamePlugin; Profile *m_CurrentProfile; diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp index c7f15dc9..8bc1dbc6 100644 --- a/src/settingsdialog.cpp +++ b/src/settingsdialog.cpp @@ -89,7 +89,7 @@ void SettingsDialog::on_categoriesBtn_clicked() void SettingsDialog::on_bsaDateBtn_clicked() { - IPluginGame *game = qApp->property("managed_game").value(); + IPluginGame const *game = qApp->property("managed_game").value(); QDir dir = game->dataDirectory(); Helper::backdateBSAs(qApp->property("dataPath").toString().toStdWString(), diff --git a/src/shared/fallout3info.h b/src/shared/fallout3info.h index ed525588..69eb9c45 100644 --- a/src/shared/fallout3info.h +++ b/src/shared/fallout3info.h @@ -40,8 +40,6 @@ public: virtual GameInfo::Type getType() { return TYPE_FALLOUT3; } - virtual std::wstring getGameName() const { return L"Fallout 3"; } - virtual std::vector getSavegameAttachmentExtensions(); // file name of this games ini (no path) diff --git a/src/shared/falloutnvinfo.h b/src/shared/falloutnvinfo.h index ee67ac17..a7ee089e 100644 --- a/src/shared/falloutnvinfo.h +++ b/src/shared/falloutnvinfo.h @@ -40,8 +40,6 @@ public: virtual GameInfo::Type getType() { return TYPE_FALLOUTNV; } - virtual std::wstring getGameName() const { return L"New Vegas"; } - virtual std::vector getSavegameAttachmentExtensions(); // file name of this games ini (no path) diff --git a/src/shared/gameinfo.h b/src/shared/gameinfo.h index de3af8b4..55161952 100644 --- a/src/shared/gameinfo.h +++ b/src/shared/gameinfo.h @@ -58,13 +58,10 @@ public: // get a list of file extensions for additional files belonging to a save game virtual std::vector getSavegameAttachmentExtensions() = 0; - //**Currently only used in a nasty mess at initialisation time. - virtual std::wstring getGameName() const = 0; - - //**USED IN HOOKDLL and in initialisation + //**USED IN HOOKDLL virtual std::wstring getGameDirectory() const; - //**USED IN HOOKDLL and initialisation + //**USED IN HOOKDLL // initialise with the path to the mo directory (needs to be where hook.dll is stored). This // needs to be called before the instance can be retrieved static bool init(const std::wstring &moDirectory, const std::wstring &gamePath = L""); diff --git a/src/shared/oblivioninfo.h b/src/shared/oblivioninfo.h index 00048930..e0a861bf 100644 --- a/src/shared/oblivioninfo.h +++ b/src/shared/oblivioninfo.h @@ -38,8 +38,6 @@ public: virtual GameInfo::Type getType() { return TYPE_OBLIVION; } - virtual std::wstring getGameName() const { return L"Oblivion"; } - virtual std::vector getSavegameAttachmentExtensions(); // file name of this games ini (no path) diff --git a/src/shared/skyriminfo.h b/src/shared/skyriminfo.h index afba1974..17b542ab 100644 --- a/src/shared/skyriminfo.h +++ b/src/shared/skyriminfo.h @@ -40,8 +40,6 @@ public: virtual GameInfo::Type getType() { return TYPE_SKYRIM; } - virtual std::wstring getGameName() const { return L"Skyrim"; } - virtual std::vector getSavegameAttachmentExtensions(); // file name of this games ini (no path) -- cgit v1.3.1