From 8aa6dc4c7dcf4139cd0144207a327013bd3cb1dc Mon Sep 17 00:00:00 2001 From: Tannin Date: Thu, 29 Jan 2015 19:26:42 +0100 Subject: extended the game-plugin interface --- src/dlls.manifest.debug.qt5 | 2 + src/dlls.manifest.qt5 | 2 + src/dummybsa.cpp | 244 ------------------------------------------- src/dummybsa.h | 64 ------------ src/loadmechanism.cpp | 91 ++++++++-------- src/main.cpp | 28 ++--- src/mainwindow.cpp | 119 ++++++++++----------- src/mainwindow.h | 2 - src/modinfo.cpp | 11 +- src/organizer.pro | 4 +- src/organizercore.cpp | 75 +++++-------- src/organizercore.h | 1 - src/pluginlist.cpp | 23 ++-- src/profile.cpp | 124 +++++----------------- src/profile.h | 15 +-- src/profilesdialog.cpp | 27 +++-- src/profilesdialog.h | 3 +- src/selectiondialog.cpp | 23 +++- src/selectiondialog.h | 5 +- src/shared/fallout3info.cpp | 46 +------- src/shared/fallout3info.h | 45 +++++--- src/shared/falloutnvinfo.cpp | 63 ----------- src/shared/falloutnvinfo.h | 43 +++++--- src/shared/gameinfo.h | 55 +--------- src/shared/oblivioninfo.cpp | 48 +-------- src/shared/oblivioninfo.h | 45 +++++--- src/shared/skyriminfo.cpp | 56 +--------- src/shared/skyriminfo.h | 16 --- 28 files changed, 338 insertions(+), 942 deletions(-) delete mode 100644 src/dummybsa.cpp delete mode 100644 src/dummybsa.h (limited to 'src') diff --git a/src/dlls.manifest.debug.qt5 b/src/dlls.manifest.debug.qt5 index e49b33b8..59497baa 100644 --- a/src/dlls.manifest.debug.qt5 +++ b/src/dlls.manifest.debug.qt5 @@ -23,5 +23,7 @@ + + diff --git a/src/dlls.manifest.qt5 b/src/dlls.manifest.qt5 index b8f2d467..76206f21 100644 --- a/src/dlls.manifest.qt5 +++ b/src/dlls.manifest.qt5 @@ -23,5 +23,7 @@ + + \ No newline at end of file diff --git a/src/dummybsa.cpp b/src/dummybsa.cpp deleted file mode 100644 index 49c6ee53..00000000 --- a/src/dummybsa.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/* -Copyright (C) 2012 Sebastian Herbord. All rights reserved. - -This file is part of Mod Organizer. - -Mod Organizer is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Mod Organizer is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Mod Organizer. If not, see . -*/ - -#include "dummybsa.h" -#include -#include -#define WIN32_LEAN_AND_MEAN -#include - - -static void writeUlong(unsigned char* buffer, int offset, unsigned long value) -{ - union { - unsigned long ulValue; - unsigned char cValue[4]; - }; - ulValue = value; - memcpy(buffer + offset, cValue, 4); -} - -static void writeUlonglong(unsigned char* buffer, int offset, unsigned long long value) -{ - union { - unsigned long long ullValue; - unsigned char cValue[8]; - }; - ullValue = value; - memcpy(buffer + offset, cValue, 8); -} -/* -static unsigned long long genHashInt(const char* pos, const char* end) -{ - unsigned long long hash2 = 0; - for (; pos < end; ++pos) { - hash2 *= 0x1003f; - hash2 += *pos; - } - return hash2; -} - - -static unsigned long long genHash(const char* fileName) -{ - char fileNameLower[MAX_PATH + 1]; - int i = 0; - for (; i < MAX_PATH && fileName[i] != '\0'; ++i) { - fileNameLower[i] = tolower(fileName[i]); - } - fileNameLower[i] = '\0'; - - char* ext = strrchr(fileNameLower, '.'); - if (ext == nullptr) { - ext = fileNameLower + strlen(fileNameLower); - } - - int length = ext - fileNameLower; - - unsigned long long hash = 0ULL; - - if (length > 0) { - hash = *(ext - 1) | - ((length > 2 ? *(ext - 2) : 0) << 8) | - (length << 16) | - (fileNameLower[0] << 24); - } - - if (strcmp(ext + 1, "dds") == 0) { - hash |= 0x8080; - } // the rest is not supported currently - - hash |= genHashInt(fileNameLower + 1, ext - 2) << 0x32; - hash |= genHashInt(ext, ext + strlen(ext)) << 0x32; - - return hash; -}*/ - - -static unsigned long genHashInt(const unsigned char *pos, const unsigned char *end) -{ - unsigned long hash = 0; - for (; pos < end; ++pos) { - hash *= 0x1003f; - hash += *pos; - } - return hash; -} - - -static unsigned long long genHash(const char* fileName) -{ - char fileNameLower[MAX_PATH + 1]; - int i = 0; - for (; i < MAX_PATH && fileName[i] != '\0'; ++i) { - fileNameLower[i] = static_cast(tolower(fileName[i])); - if (fileNameLower[i] == '\\') { - fileNameLower[i] = '/'; - } - } - fileNameLower[i] = '\0'; - - unsigned char *fileNameLowerU = reinterpret_cast(fileNameLower); - - char* ext = strrchr(fileNameLower, '.'); - if (ext == nullptr) { - ext = fileNameLower + strlen(fileNameLower); - } - unsigned char *extU = reinterpret_cast(ext); - - int length = ext - fileNameLower; - - unsigned long long hash = 0ULL; - - if (length > 0) { - hash = *(extU - 1) | - ((length > 2 ? *(ext - 2) : 0) << 8) | - (length << 16) | - (fileNameLowerU[0] << 24); - } - - if (strlen(ext) > 0) { - if (strcmp(ext + 1, "kf") == 0) { - hash |= 0x80; - } else if (strcmp(ext + 1, "nif") == 0) { - hash |= 0x8000; - } else if (strcmp(ext + 1, "dds") == 0) { - hash |= 0x8080; - } else if (strcmp(ext + 1, "wav") == 0) { - hash |= 0x80000000; - } - - unsigned long long temp = static_cast(genHashInt( - fileNameLowerU + 1, extU - 2)); - temp += static_cast(genHashInt( - extU, extU + strlen(ext))); - - hash |= (temp & 0xFFFFFFFF) << 32; - } - return hash; -} - - -DummyBSA::DummyBSA() - : m_Version(MOShared::GameInfo::instance().getBSAVersion()), m_FolderName(""), m_FileName("dummy.dds"), - m_TotalFileNameLength(0) -{ -} - - -void DummyBSA::writeHeader(QFile& file) -{ - unsigned char header[] = { - 'B', 'S', 'A', '\0', // magic string - 0xDE, 0xAD, 0xBE, 0xEF, // version - insert later - 0x24, 0x00, 0x00, 0x00, // offset to folder recors. header size is static - 0xDE, 0xAD, 0xBE, 0xEF, // archive flags - insert later - 0x01, 0x00, 0x00, 0x00, // folder count - 0x01, 0x00, 0x00, 0x00, // file count - 0xDE, 0xAD, 0xBE, 0xEF, // total folder names length - insert later - 0xDE, 0xAD, 0xBE, 0xEF, // total file names length - insert later - 0xDE, 0xAD, 0xBE, 0xEF // file flags - insert later - }; - - writeUlong(header, 4, MOShared::GameInfo::instance().getBSAVersion()); - writeUlong(header, 12, 0x01 | 0x02); // has directories and has files. - writeUlong(header, 24, m_FolderName.length() + 1); // empty folder name - writeUlong(header, 28, m_TotalFileNameLength); // single character file name - - writeUlong(header, 32, 2); // has dds - - file.write(reinterpret_cast(header), sizeof(header)); -} - - -void DummyBSA::writeFolderRecord(QFile& file, const std::string& folderName) -{ - unsigned char folderRecord[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, // folder hash - 0x01, 0x00, 0x00, 0x00, // file count - 0xDE, 0xAD, 0xBE, 0xEF, // offset to folder name - }; - // we'd usually have to sort folders be the hash value generated here - writeUlonglong(folderRecord, 0, genHash(folderName.c_str())); - writeUlong( folderRecord, 12, 0x34 + m_TotalFileNameLength); // TODO: this should be calculated properly - - file.write(reinterpret_cast(folderRecord), sizeof(folderRecord)); -} - - -void DummyBSA::writeFileRecord(QFile& file, const std::string& fileName) -{ - unsigned char fileRecord[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, // file name hash - 0xDE, 0xAD, 0xBE, 0xEF, // size - 0xDE, 0xAD, 0xBE, 0xEF, // offset to file data - }; - - // we'd usually have to sort files by the value generated here - writeUlonglong(fileRecord, 0, genHash(fileName.c_str())); - writeUlong( fileRecord, 8, 0); - writeUlong( fileRecord, 12, 0x44 + (fileName.length() + 1) + 4); // after this record we expect the filename and 4 bytes of file size - - file.write(reinterpret_cast(fileRecord), sizeof(fileRecord)); -} - - -void DummyBSA::writeFileRecordBlocks(QFile& file, const std::string& folderName) -{ - file.write(folderName.c_str(), folderName.length() + 1); - - writeFileRecord(file, m_FileName); -} - - -void DummyBSA::write(const QString& fileName) -{ - QFile file(fileName); - file.open(QIODevice::WriteOnly); - - m_TotalFileNameLength = m_FileName.length() + 1; - - writeHeader(file); - writeFolderRecord(file, m_FolderName); - writeFileRecordBlocks(file, m_FolderName); - file.write(m_FileName.c_str() , m_FileName.length() + 1); - char fileSize[] = { 0x00, 0x00, 0x00, 0x00 }; - file.write(fileSize, sizeof(fileSize)); - file.close(); -} diff --git a/src/dummybsa.h b/src/dummybsa.h deleted file mode 100644 index 0d231393..00000000 --- a/src/dummybsa.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -Copyright (C) 2012 Sebastian Herbord. All rights reserved. - -This file is part of Mod Organizer. - -Mod Organizer is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Mod Organizer is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Mod Organizer. If not, see . -*/ - -#ifndef DUMMYBSA_H -#define DUMMYBSA_H - -#include -#include - -/** - * @brief Class for creating a dummy bsa used for archive invalidation - **/ -class DummyBSA -{ - -public: - - /** - * @brief constructor - * - **/ - DummyBSA(); - - /** - * @brief write to the specified file - * - * @param fileName name of the file to write to - **/ - void write(const QString& fileName); - -private: - - void writeHeader(QFile& file); - void writeFolderRecord(QFile& file, const std::string& folderName); - void writeFileRecord(QFile& file, const std::string& fileName); - void writeFileRecordBlocks(QFile& file, const std::string& folderName); - -private: - - unsigned long m_Version; - std::string m_FolderName; - std::string m_FileName; - unsigned long m_TotalFileNameLength; - -}; - - -#endif // DUMMYBSA_H diff --git a/src/loadmechanism.cpp b/src/loadmechanism.cpp index 711a7f1a..913d018c 100644 --- a/src/loadmechanism.cpp +++ b/src/loadmechanism.cpp @@ -20,7 +20,8 @@ along with Mod Organizer. If not, see . #include "loadmechanism.h" #include "utility.h" #include "util.h" -#include +#include +#include #include #include #include @@ -28,6 +29,7 @@ along with Mod Organizer. If not, see . #include #include #include +#include using namespace MOBase; @@ -49,7 +51,7 @@ void LoadMechanism::writeHintFile(const QDir &targetDirectory) if (!hintFile.open(QIODevice::WriteOnly)) { throw MyException(QObject::tr("failed to open %1: %2").arg(hintFilePath).arg(hintFile.errorString())); } - hintFile.write(ToString(GameInfo::instance().getOrganizerDirectory(), true).c_str()); + hintFile.write(qApp->applicationDirPath().toUtf8().constData()); hintFile.close(); } @@ -62,38 +64,31 @@ void LoadMechanism::removeHintFile(QDir &targetDirectory) bool LoadMechanism::isDirectLoadingSupported() { - if (GameInfo::instance().getType() == GameInfo::TYPE_OBLIVION) { + IPluginGame *game = qApp->property("managed_game").value(); + if (game->gameName().compare("oblivion", Qt::CaseInsensitive)) { // oblivion can be loaded directly if it's not the steam variant - QString gamePath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getGameDirectory())); - QDir gameDir(gamePath); - // test if this is the steam version of oblivion - if (QFile(gameDir.absoluteFilePath("steam_api.dll")).exists()) { - return false; - } + return !game->gameDirectory().exists("steam_api.dll"); + } else { + // all other games work afaik + return true; } - - // all other games work afaik - return true; } - bool LoadMechanism::isScriptExtenderSupported() { - QString targetPath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getGameDirectory())); - if ((QFile(targetPath.mid(0).append("/").append(ToQString(GameInfo::instance().getSEName())).append("_loader.exe")).exists()) || - (QFile(targetPath.mid(0).append("/").append(ToQString(GameInfo::instance().getSEName())).append("_steam_loader.dll")).exists())) { - return true; - } else { - return false; - } -} + IPluginGame *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 + return (extender != nullptr) + && (game->gameDirectory().exists(extender->name() + "_loader.exe") + || game->gameDirectory().exists(extender->name() + "_steam_loader.dll")); +} bool LoadMechanism::isProxyDLLSupported() { - QString targetPath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getGameDirectory())); - targetPath.append("/").append(ToQString(AppConfig::proxyDLLTarget())); - return QFile(targetPath).exists(); + IPluginGame *game = qApp->property("managed_game").value(); + return game->gameDirectory().exists(QString::fromStdWString(AppConfig::proxyDLLTarget())); } @@ -124,12 +119,13 @@ bool LoadMechanism::hashIdentical(const QString &fileNameLHS, const QString &fil void LoadMechanism::deactivateScriptExtender() { try { - QString gameDirectory = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getGameDirectory())); - - QString pluginsDirPath = gameDirectory; - pluginsDirPath.append("/data/").append(ToQString(GameInfo::instance().getSEName())).append("/plugins"); + IPluginGame *game = qApp->property("managed_game").value(); + ScriptExtender *extender = game->feature(); + if (extender == nullptr) { + throw MyException(QObject::tr("game doesn't support a script extender")); + } - QDir pluginsDir(pluginsDirPath); + QDir pluginsDir(game->gameDirectory().absolutePath() + "/data/" + extender->name() + "/plugins"); QString hookDLLName = ToQString(AppConfig::hookDLLName()); if (QFile(pluginsDir.absoluteFilePath(hookDLLName)).exists()) { @@ -149,14 +145,13 @@ void LoadMechanism::deactivateScriptExtender() void LoadMechanism::deactivateProxyDLL() { try { - QString gameDirectory = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getGameDirectory())); + IPluginGame *game = qApp->property("managed_game").value(); - QString targetPath = gameDirectory; - targetPath.append("/").append(ToQString(AppConfig::proxyDLLTarget())); + QString targetPath = game->gameDirectory().absoluteFilePath(QString::fromStdWString(AppConfig::proxyDLLTarget())); QFile targetDLL(targetPath); if (targetDLL.exists()) { - QString origFile = gameDirectory.mid(0).append(ToQString(AppConfig::proxyDLLOrig())); + QString origFile = game->gameDirectory().absoluteFilePath(QString::fromStdWString(AppConfig::proxyDLLOrig())); // determine if a proxy-dll is installed // this is a very crude way of making this decision but it should be good enough if ((targetDLL.size() < 24576) && (QFile(origFile).exists())) { @@ -169,8 +164,7 @@ void LoadMechanism::deactivateProxyDLL() } } - QDir dir(gameDirectory); - removeHintFile(dir); + removeHintFile(game->gameDirectory()); } catch (const std::exception &e) { QMessageBox::critical(nullptr, QObject::tr("Failed to deactivate proxy-dll loading"), e.what()); } @@ -180,19 +174,20 @@ void LoadMechanism::deactivateProxyDLL() void LoadMechanism::activateScriptExtender() { try { - QString gameDirectory = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getGameDirectory())); - - QString pluginsDirPath = gameDirectory; - pluginsDirPath.append("/data/").append(ToQString(GameInfo::instance().getSEName())).append("/plugins"); + IPluginGame *game = qApp->property("managed_game").value(); + ScriptExtender *extender = game->feature(); + if (extender == nullptr) { + throw MyException(QObject::tr("game doesn't support a script extender")); + } - QDir pluginsDir(pluginsDirPath); + QDir pluginsDir(game->gameDirectory().absolutePath() + "/data/" + extender->name() + "/plugins"); if (!pluginsDir.exists()) { pluginsDir.mkpath("."); } QString targetPath = pluginsDir.absoluteFilePath(ToQString(AppConfig::hookDLLName())); - QString hookDLLPath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOrganizerDirectory())).append("/").append(ToQString(AppConfig::hookDLLName())); + QString hookDLLPath = qApp->applicationDirPath() + "/" + QString::fromStdWString(AppConfig::hookDLLName()); QFile dllFile(targetPath); @@ -219,17 +214,16 @@ void LoadMechanism::activateScriptExtender() void LoadMechanism::activateProxyDLL() { try { - QString gameDirectory = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getGameDirectory())); + IPluginGame *game = qApp->property("managed_game").value(); + + QString targetPath = game->gameDirectory().absoluteFilePath(QString::fromStdWString(AppConfig::proxyDLLTarget())); - QString targetPath = gameDirectory; - targetPath.append("/").append(ToQString(AppConfig::proxyDLLTarget())); QFile targetDLL(targetPath); if (!targetDLL.exists()) { return; } - QString sourcePath = QDir::fromNativeSeparators( - ToQString(GameInfo::instance().getOrganizerDirectory())).append("/").append(ToQString(AppConfig::proxyDLLSource())); + QString sourcePath = qApp->applicationDirPath() + "/" + ToQString(AppConfig::proxyDLLSource()); // this is a very crude way of making this decision but it should be good enough if (targetDLL.size() < 24576) { @@ -246,8 +240,7 @@ void LoadMechanism::activateProxyDLL() } else { // no proxy dll installed yet. move the original and insert proxy-dll - QString origFile = gameDirectory; - origFile.append("/").append(ToQString(AppConfig::proxyDLLOrig())); + QString origFile = game->gameDirectory().absoluteFilePath(QString::fromStdWString(AppConfig::proxyDLLOrig())); if (QFile(origFile).exists()) { // orig-file exists. this may happen if the steam-api was updated or the user messed with the @@ -263,7 +256,7 @@ void LoadMechanism::activateProxyDLL() throw MyException(QObject::tr("Failed to copy %1 to %2").arg(sourcePath).arg(targetPath)); } } - writeHintFile(QDir(gameDirectory)); + writeHintFile(game->gameDirectory()); } catch (const std::exception &e) { QMessageBox::critical(nullptr, QObject::tr("Failed to set up proxy-dll loading"), e.what()); } diff --git a/src/main.cpp b/src/main.cpp index a048d50d..8507d725 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -406,29 +406,17 @@ int main(int argc, char *argv[]) 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); - - { // add options - QString skyrimPath = ToQString(SkyrimInfo::getRegPathStatic()); - QString falloutNVPath = ToQString(FalloutNVInfo::getRegPathStatic()); - QString fallout3Path = ToQString(Fallout3Info::getRegPathStatic()); - QString oblivionPath = ToQString(OblivionInfo::getRegPathStatic()); - if (skyrimPath.length() != 0) { - selection.addChoice(QString("Skyrim"), skyrimPath, skyrimPath); - } - if (falloutNVPath.length() != 0) { - selection.addChoice(QString("Fallout NV"), falloutNVPath, falloutNVPath); - } - if (fallout3Path.length() != 0) { - selection.addChoice(QString("Fallout 3"), fallout3Path, fallout3Path); - } - if (oblivionPath.length() != 0) { - selection.addChoice(QString("Oblivion"), oblivionPath, oblivionPath); - } + SelectionDialog selection(QObject::tr("Please select the game to manage"), nullptr, QSize(32, 32)); - selection.addChoice(QString("Browse..."), QString(), QString()); + 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; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 50a07b75..1c54d250 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -60,13 +60,15 @@ along with Mod Organizer. If not, see . #include "aboutdialog.h" #include "safewritefile.h" #include "organizerproxy.h" -#include "nxmaccessmanager.h +#include "nxmaccessmanager.h" #include #include #include #include #include +#include #include +#include #include #include #include @@ -139,7 +141,7 @@ using namespace MOShared; MainWindow::MainWindow(const QString &exeName - : QMainWindow(parent), ui(new Ui::MainWindow), m_Tutorial(this, "MainWindow"), + , QSettings &initSettings , OrganizerCore &organizerCore , PluginContainer &pluginContainer , QWidget *parent) @@ -148,7 +150,7 @@ MainWindow::MainWindow(const QString &exeName , m_WasVisible(false) , m_Tutorial(this, "MainWindow") , m_ExeName(exeName) - , m_OldProfileIndex(-1), + , m_OldProfileIndex(-1) , m_ModListGroupingProxy(nullptr) , m_ModListSortProxy(nullptr) , m_OldExecutableIndex(-1) @@ -191,7 +193,7 @@ MainWindow::MainWindow(const QString &exeName updateToolBar(); - languageChange(m_Settings.language()); + TaskProgressManager::instance().tryCreateTaskbar(); // set up mod list m_ModListSortProxy = m_OrganizerCore.createModListProxyModel(); @@ -335,7 +337,7 @@ MainWindow::MainWindow(const QString &exeName // refresh profiles so the current profile can be activated refreshProfiles(false); - ui->profileBox->setCurrentText(m_OrganizerCore.currentProfile()->getName()); + ui->profileBox->setCurrentText(m_OrganizerCore.currentProfile()->name()); refreshExecutablesList(); updateToolBar(); @@ -1036,9 +1038,9 @@ void MainWindow::on_profileBox_currentIndexChanged(int index) } if (ui->profileBox->currentIndex() == 0) { - ProfilesDialog(m_GamePath, m_OrganizerCore.managedGame(), this).exec(); + ProfilesDialog(m_GamePath, this).exec(); while (!refreshProfiles()) { - ProfilesDialog(m_GamePath, m_OrganizerCore.managedGame(), this).exec(); + ProfilesDialog(m_GamePath, this).exec(); } ui->profileBox->setCurrentIndex(previousIndex); } else { @@ -1213,25 +1215,6 @@ bool MainWindow::refreshProfiles(bool selectProfile) } -#if QT_VERSION >= 0x050000 -extern QPixmap qt_pixmapFromWinHICON(HICON icon); -#else -#define qt_pixmapFromWinHICON(icon) QPixmap::fromWinHICON(icon) -#endif - -QIcon MainWindow::iconForExecutable(const QString &filePath) -{ - HICON winIcon; - UINT res = ::ExtractIconExW(ToWString(filePath).c_str(), 0, &winIcon, nullptr, 1); - if (res == 1) { - QIcon result = QIcon(qt_pixmapFromWinHICON(winIcon)); - ::DestroyIcon(winIcon); - return result; - } else { - return QIcon(":/MO/gui/executable"); - } -} - void MainWindow::refreshExecutablesList() { QComboBox* executablesList = findChild("executablesListBox"); @@ -1285,12 +1268,12 @@ void MainWindow::refreshSaveList() QDir savesDir; if (m_OrganizerCore.currentProfile()->localSavesEnabled()) { - savesDir.setPath(m_OrganizerCore.currentProfile()->getPath() + "/saves"); + savesDir.setPath(m_OrganizerCore.currentProfile()->absolutePath() + "/saves"); } else { wchar_t path[MAX_PATH]; ::GetPrivateProfileStringW(L"General", L"SLocalSavePath", L"Saves", path, MAX_PATH, - (ToWString(m_OrganizerCore.currentProfile()->getPath()) + L"\\" + GameInfo::instance().getIniFileNames().at(0)).c_str()); + (ToWString(m_OrganizerCore.currentProfile()->absolutePath()) + L"\\" + GameInfo::instance().getIniFileNames().at(0)).c_str()); savesDir.setPath(m_OrganizerCore.managedGame()->documentsDirectory().absoluteFilePath(QString::fromWCharArray(path))); } @@ -1417,42 +1400,46 @@ void MainWindow::updateBSAList(const QStringList &defaultArchives, const QString void MainWindow::checkBSAList() { - ui->bsaList->blockSignals(true); + DataArchives *archives = m_OrganizerCore.managedGame()->feature(); - QStringList defaultArchives = m_OrganizerCore.defaultArchiveList(); + if (archives != nullptr) { + ui->bsaList->blockSignals(true); - bool warning = false; + QStringList defaultArchives = archives->archives(m_OrganizerCore.currentProfile()); - for (int i = 0; i < ui->bsaList->topLevelItemCount(); ++i) { - bool modWarning = false; - QTreeWidgetItem *tlItem = ui->bsaList->topLevelItem(i); - for (int j = 0; j < tlItem->childCount(); ++j) { - QTreeWidgetItem *item = tlItem->child(j); - QString filename = item->text(0); - item->setIcon(0, QIcon()); - item->setToolTip(0, QString()); + bool warning = false; - if (item->checkState(0) == Qt::Unchecked) { - if (defaultArchives.contains(filename)) { - item->setIcon(0, QIcon(":/MO/gui/warning")); - item->setToolTip(0, tr("This bsa is enabled in the ini file so it may be required!")); - modWarning = true; + for (int i = 0; i < ui->bsaList->topLevelItemCount(); ++i) { + bool modWarning = false; + QTreeWidgetItem *tlItem = ui->bsaList->topLevelItem(i); + for (int j = 0; j < tlItem->childCount(); ++j) { + QTreeWidgetItem *item = tlItem->child(j); + QString filename = item->text(0); + item->setIcon(0, QIcon()); + item->setToolTip(0, QString()); + + if (item->checkState(0) == Qt::Unchecked) { + if (defaultArchives.contains(filename)) { + item->setIcon(0, QIcon(":/MO/gui/warning")); + item->setToolTip(0, tr("This bsa is enabled in the ini file so it may be required!")); + modWarning = true; + } } } + if (modWarning) { + ui->bsaList->expandItem(ui->bsaList->topLevelItem(i)); + warning = true; + } } - if (modWarning) { - ui->bsaList->expandItem(ui->bsaList->topLevelItem(i)); - warning = true; + + if (warning) { + ui->tabWidget->setTabIcon(1, QIcon(":/MO/gui/warning")); + } else { + ui->tabWidget->setTabIcon(1, QIcon()); } - } - if (warning) { - ui->tabWidget->setTabIcon(1, QIcon(":/MO/gui/warning")); - } else { - ui->tabWidget->setTabIcon(1, QIcon()); + ui->bsaList->blockSignals(false); } - - ui->bsaList->blockSignals(false); } @@ -1790,7 +1777,7 @@ void MainWindow::on_actionAdd_Profile_triggered() { bool repeat = true; while (repeat) { - ProfilesDialog profilesDialog(m_GamePath, m_OrganizerCore.managedGame(), this); + ProfilesDialog profilesDialog(m_GamePath, this); profilesDialog.exec(); if (refreshProfiles() && !profilesDialog.failed()) { repeat = false; @@ -2333,10 +2320,10 @@ void MainWindow::overwriteClosed(int) void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, int tab) { - if (!m_OrganizerCore.modList()->modInfoAboutToChange(modInfo)) { - qDebug("A different mod information dialog is open. If this is incorrect, please restart MO"); - return; - } + if (!m_OrganizerCore.modList()->modInfoAboutToChange(modInfo)) { + qDebug("A different mod information dialog is open. If this is incorrect, please restart MO"); + return; + } std::vector flags = modInfo->getFlags(); if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end()) { QDialog *dialog = this->findChild("__overwriteDialog"); @@ -3379,7 +3366,7 @@ void MainWindow::installTranslator(const QString &name) QString fileName = name + "_" + m_CurrentLanguage; if (!translator->load(fileName, qApp->applicationDirPath() + "/translations")) { if ((m_CurrentLanguage != "en-US") && (m_CurrentLanguage != "en_US")) { - qWarning("localization file %s not found", qPrintable(fileName)); + qDebug("localization file %s not found", qPrintable(fileName)); } // we don't actually expect localization files for english } @@ -3481,10 +3468,10 @@ int MainWindow::getBinaryExecuteInfo(const QFileInfo &targetInfo, QFileInfo &bin { // try to find java automatically WCHAR buffer[MAX_PATH]; - if (::FindExecutableW(targetPathW.c_str(), nullptr, buffer) > (HINSTANCE)32) { - DWORD binaryType = 0UL; - if (!::GetBinaryTypeW(buffer, &binaryType)) { - qDebug("failed to determine binary type of \"%ls\": %lu", buffer, ::GetLastError()); + if (::FindExecutableW(targetPathW.c_str(), nullptr, buffer) > (HINSTANCE)32) { + DWORD binaryType = 0UL; + if (!::GetBinaryTypeW(buffer, &binaryType)) { + qDebug("failed to determine binary type of \"%ls\": %lu", buffer, ::GetLastError()); } else if (binaryType == SCS_32BIT_BINARY) { binaryPath = ToQString(buffer); } @@ -3659,7 +3646,7 @@ void MainWindow::openDataFile() QString arguments; switch (getBinaryExecuteInfo(targetInfo, binaryInfo, arguments)) { case 1: { - m_OrganizerCore.spawnBinaryDirect(binaryInfo, arguments, m_OrganizerCore.currentProfile()->getName(), targetInfo.absolutePath(), ""); + m_OrganizerCore.spawnBinaryDirect(binaryInfo, arguments, m_OrganizerCore.currentProfile()->name(), targetInfo.absolutePath(), ""); } break; case 2: { ::ShellExecuteW(nullptr, L"open", ToWString(targetInfo.absoluteFilePath()).c_str(), nullptr, nullptr, SW_SHOWNORMAL); @@ -4339,7 +4326,7 @@ void MainWindow::on_bossButton_clicked() createStdoutPipe(&stdOutRead, &stdOutWrite); HANDLE loot = startBinary(QFileInfo(qApp->applicationDirPath() + "/loot/lootcli.exe"), parameters.join(" "), - m_OrganizerCore.currentProfile()->getName(), + m_OrganizerCore.currentProfile()->name(), m_OrganizerCore.settings().logLevel(), qApp->applicationDirPath() + "/loot", true, diff --git a/src/mainwindow.h b/src/mainwindow.h index b9f93cd5..d0e3aaf5 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -229,8 +229,6 @@ private: bool errorReported(QString &logFile); - QIcon iconForExecutable(const QString &filePath); - void updateESPLock(bool locked); static void setupNetworkProxy(bool activate); diff --git a/src/modinfo.cpp b/src/modinfo.cpp index b1d9bed4..3b8d6b92 100644 --- a/src/modinfo.cpp +++ b/src/modinfo.cpp @@ -28,8 +28,10 @@ along with Mod Organizer. If not, see . #include "messagedialog.h" #include +#include #include #include +#include #include @@ -862,7 +864,13 @@ std::vector ModInfoRegular::getContents() const if (dir.entryList(QStringList() << "*.esp" << "*.esm").size() > 0) { result.push_back(CONTENT_PLUGIN); } - QString sePluginPath = ToQString(GameInfo::instance().getSEName()) + "/plugins"; + + ScriptExtender *extender = qApp->property("managed_game").value()->feature(); + + if (extender != nullptr) { + QString sePluginPath = extender->name() + "/plugins"; + if (dir.exists(sePluginPath)) result.push_back(CONTENT_SKSE); + } if (dir.exists("textures")) result.push_back(CONTENT_TEXTURE); if (dir.exists("meshes")) result.push_back(CONTENT_MESH); if (dir.exists("interface") @@ -870,7 +878,6 @@ std::vector ModInfoRegular::getContents() const if (dir.exists("music")) result.push_back(CONTENT_MUSIC); if (dir.exists("sound")) result.push_back(CONTENT_SOUND); if (dir.exists("scripts")) result.push_back(CONTENT_SCRIPT); - if (dir.exists(sePluginPath)) result.push_back(CONTENT_SKSE); if (dir.exists("strings")) result.push_back(CONTENT_STRING); if (dir.exists("SkyProc Patchers")) result.push_back(CONTENT_SKYPROC); return result; diff --git a/src/organizer.pro b/src/organizer.pro index b67fb3e5..9300f348 100644 --- a/src/organizer.pro +++ b/src/organizer.pro @@ -57,7 +57,6 @@ SOURCES += \ filedialogmemory.cpp \ executableslist.cpp \ editexecutablesdialog.cpp \ - dummybsa.cpp \ downloadmanager.cpp \ downloadlistwidgetcompact.cpp \ downloadlistwidget.cpp \ @@ -137,7 +136,6 @@ HEADERS += \ filedialogmemory.h \ executableslist.h \ editexecutablesdialog.h \ - dummybsa.h \ downloadmanager.h \ downloadlistwidgetcompact.h \ downloadlistwidget.h \ @@ -257,7 +255,7 @@ LIBS += -L"E:/Visual Leak Detector/lib/Win32" #DEFINES += TEST_MODELS -INCLUDEPATH += ../shared ../archive ../uibase ../bsatk ../esptk "$${LOOTPATH}" "$${BOOSTPATH}" +INCLUDEPATH += ../shared ../archive ../uibase ../bsatk ../esptk ../plugins/gamefeatures "$${LOOTPATH}" "$${BOOSTPATH}" LIBS += -L"$${BOOSTPATH}/stage/lib" diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 936e5529..0ea3ccb1 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -11,7 +11,9 @@ #include "spawn.h" #include "safewritefile.h" #include "syncoverwritedialog.h" +#include "nxmaccessmanager.h" #include +#include #include #include #include @@ -184,7 +186,7 @@ void OrganizerCore::storeSettings() m_UserInterface->storeSettings(settings); } if (m_CurrentProfile != nullptr) { - settings.setValue("selected_profile", m_CurrentProfile->getName().toUtf8().constData()); + settings.setValue("selected_profile", m_CurrentProfile->name().toUtf8().constData()); } settings.setValue("ask_for_nexuspw", m_AskForNexusPW); @@ -368,6 +370,7 @@ void OrganizerCore::setManagedGame(const QString &gameName) m_GameName = gameName; if (m_PluginContainer != nullptr) { m_GamePlugin = m_PluginContainer->managedGame(m_GameName); + qApp->setProperty("managed_game", QVariant::fromValue(m_GamePlugin)); emit managedGameChanged(m_GamePlugin); } } @@ -473,7 +476,6 @@ InstallationManager *OrganizerCore::installationManager() void OrganizerCore::createDefaultProfile() { QString profilesPath = qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::profilesPath()); - qDebug("%d", QDir(profilesPath).entryList(QDir::AllDirs | QDir::NoDotAndDotDot).size()); if (QDir(profilesPath).entryList(QDir::AllDirs | QDir::NoDotAndDotDot).size() == 0) { Profile newProf("Default", managedGame(), false); } @@ -506,7 +508,7 @@ MOBase::IModRepositoryBridge *OrganizerCore::createNexusBridge() const QString OrganizerCore::profileName() const { if (m_CurrentProfile != nullptr) { - return m_CurrentProfile->getName(); + return m_CurrentProfile->name(); } else { return ""; } @@ -515,7 +517,7 @@ QString OrganizerCore::profileName() const QString OrganizerCore::profilePath() const { if (m_CurrentProfile != nullptr) { - return m_CurrentProfile->getPath(); + return m_CurrentProfile->absolutePath(); } else { return ""; } @@ -809,7 +811,7 @@ void OrganizerCore::spawnBinary(const QFileInfo &binary, const QString &argument dialog->show(); ON_BLOCK_EXIT([&] () { dialog->hide(); dialog->deleteLater(); }); - HANDLE processHandle = spawnBinaryDirect(binary, arguments, m_CurrentProfile->getName(), currentDirectory, steamAppID); + HANDLE processHandle = spawnBinaryDirect(binary, arguments, m_CurrentProfile->name(), currentDirectory, steamAppID); if (processHandle != INVALID_HANDLE_VALUE) { if (closeAfterStart && (m_UserInterface != nullptr)) { m_UserInterface->closeWindow(); @@ -938,7 +940,7 @@ HANDLE OrganizerCore::startApplication(const QString &executable, const QStringL QString profileName = profile; if (profile.length() == 0) { if (m_CurrentProfile != nullptr) { - profileName = m_CurrentProfile->getName(); + profileName = m_CurrentProfile->name(); } else { throw MyException(tr("No profile set")); } @@ -1081,7 +1083,7 @@ void OrganizerCore::refreshESPList() // clear list try { - m_PluginList.refresh(m_CurrentProfile->getName(), + m_PluginList.refresh(m_CurrentProfile->name(), *m_DirectoryStructure, m_CurrentProfile->getPluginsFileName(), m_CurrentProfile->getLoadOrderFileName(), @@ -1091,55 +1093,34 @@ void OrganizerCore::refreshESPList() } } -QStringList OrganizerCore::defaultArchiveList() -{ - QStringList result; - wchar_t buffer[256]; - std::wstring iniFileName = ToWString(QDir::toNativeSeparators(m_CurrentProfile->getIniFileName())); - - if (::GetPrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().append(L"2").c_str(), - L"", buffer, 256, iniFileName.c_str()) != 0) { - result.append(ToQString(buffer).split(',')); - } - - for (int i = 0; i < result.count(); ++i) { - result[i] = result[i].trimmed(); - } - - return result; -} - void OrganizerCore::refreshBSAList() { - m_ArchivesInit = false; + DataArchives *archives = m_GamePlugin->feature(); - m_DefaultArchives = defaultArchiveList(); + if (archives != nullptr) { + m_ArchivesInit = false; - wchar_t buffer[256]; - std::wstring iniFileName = ToWString(QDir::toNativeSeparators(m_CurrentProfile->getIniFileName())); - if (::GetPrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(), - L"", buffer, 256, iniFileName.c_str()) != 0) { - m_DefaultArchives = ToQString(buffer).split(','); - } else { - std::vector vanillaBSAs = GameInfo::instance().getVanillaBSAs(); - for (auto iter = vanillaBSAs.begin(); iter != vanillaBSAs.end(); ++iter) { - m_DefaultArchives.append(ToQString(*iter)); + // default archives are the ones enabled outside MO. if the list can't be found (which might + // happen if ini files are missing) use hard-coded defaults (preferrably the same the game would use) + m_DefaultArchives = archives->archives(m_CurrentProfile); + if (m_DefaultArchives.length() == 0) { + m_DefaultArchives = archives->vanillaArchives(); } - } - m_ActiveArchives.clear(); + m_ActiveArchives.clear(); - auto iter = enabledArchives(); - m_ActiveArchives = toStringList(iter.begin(), iter.end()); - if (m_ActiveArchives.isEmpty()) { - m_ActiveArchives = m_DefaultArchives; - } + auto iter = enabledArchives(); + m_ActiveArchives = toStringList(iter.begin(), iter.end()); + if (m_ActiveArchives.isEmpty()) { + m_ActiveArchives = m_DefaultArchives; + } - if (m_UserInterface != nullptr) { - m_UserInterface->updateBSAList(m_DefaultArchives, m_ActiveArchives); - } + if (m_UserInterface != nullptr) { + m_UserInterface->updateBSAList(m_DefaultArchives, m_ActiveArchives); + } - m_ArchivesInit = true; + m_ArchivesInit = true; + } } void OrganizerCore::refreshLists() diff --git a/src/organizercore.h b/src/organizercore.h index 4d9b0a7c..3191e2a9 100644 --- a/src/organizercore.h +++ b/src/organizercore.h @@ -155,7 +155,6 @@ public: bool onAboutToRun(const std::function &func); bool onFinishedRun(const std::function &func); void refreshModList(bool saveChanges = true); - QStringList defaultArchiveList(); public: // IPluginDiagnose interface diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index ad177247..3c7af59f 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -26,6 +26,7 @@ along with Mod Organizer. If not, see . #include "modinfo.h" #include #include +#include #include #include @@ -126,16 +127,19 @@ QString PluginList::getColumnToolTip(int column) } -void PluginList::refresh(const QString &profileName, const DirectoryEntry &baseDirectory, - const QString &pluginsFile, const QString &loadOrderFile, - const QString &lockedOrderFile) +void PluginList::refresh(const QString &profileName + , const DirectoryEntry &baseDirectory + , const QString &pluginsFile + , const QString &loadOrderFile + , const QString &lockedOrderFile) { ChangeBracket layoutChange(this); m_ESPsByName.clear(); m_ESPsByPriority.clear(); m_ESPs.clear(); - std::vector primaryPlugins = GameInfo::instance().getPrimaryPlugins(); + + QStringList primaryPlugins = qApp->property("managed_game").value()->getPrimaryPlugins(); m_CurrentProfile = profileName; @@ -150,7 +154,7 @@ void PluginList::refresh(const QString &profileName, const DirectoryEntry &baseD if ((extension == "esp") || (extension == "esm")) { bool forceEnabled = Settings::instance().forceEnableCoreFiles() && - std::find(primaryPlugins.begin(), primaryPlugins.end(), ToWString(filename.toLower())) != primaryPlugins.end(); + std::find(primaryPlugins.begin(), primaryPlugins.end(), filename.toLower()) != primaryPlugins.end(); bool archive = false; try { @@ -321,11 +325,10 @@ bool PluginList::readLoadOrder(const QString &fileName) int priority = 0; - std::vector primaryPlugins = GameInfo::instance().getPrimaryPlugins(); - for (std::vector::iterator iter = primaryPlugins.begin(); - iter != primaryPlugins.end(); ++iter) { - if (availableESPs.find(ToQString(*iter)) != availableESPs.end()) { - m_ESPLoadOrder[ToQString(*iter)] = priority++; + QStringList primaryPlugins = qApp->property("managed_game").value()->getPrimaryPlugins(); + for (const QString &plugin : primaryPlugins) { + if (availableESPs.find(plugin) != availableESPs.end()) { + m_ESPLoadOrder[plugin] = priority++; } } diff --git a/src/profile.cpp b/src/profile.cpp index dd6814fd..5d31533a 100644 --- a/src/profile.cpp +++ b/src/profile.cpp @@ -21,7 +21,6 @@ along with Mod Organizer. If not, see . #include "report.h" #include "gameinfo.h" #include "windows_error.h" -#include "dummybsa.h" #include "modinfo.h" #include "safewritefile.h" #include @@ -29,6 +28,8 @@ along with Mod Organizer. If not, see . #include #include #include +#include +#include #include #include #include @@ -58,6 +59,7 @@ void Profile::touchFile(QString fileName) Profile::Profile(const QString &name, IPluginGame *gamePlugin, bool useDefaultSettings) : m_SaveTimer(nullptr) + , m_GamePlugin(gamePlugin) { initTimer(); QString profilesDir = qApp->property("dataPath").toString() + "/" + ToQString(AppConfig::profilesPath()); @@ -120,8 +122,9 @@ Profile::Profile(const QDir &directory, IPluginGame *gamePlugin) } -Profile::Profile(const Profile& reference) - : m_Directory(reference.m_Directory), m_SaveTimer(nullptr) +Profile::Profile(const Profile &reference) + : m_Directory(reference.m_Directory) + , m_SaveTimer(nullptr) { initTimer(); refreshModStatus(); @@ -590,35 +593,22 @@ void Profile::mergeTweaks(ModInfo::Ptr modInfo, const QString &tweakedIni) const bool Profile::invalidationActive(bool *supported) const { - if (GameInfo::instance().requiresBSAInvalidation()) { + IPluginGame *gamePlugin = qApp->property("managed_game").value(); + + BSAInvalidation *invalidation = gamePlugin->feature(); + DataArchives *dataArchives = gamePlugin->feature(); + + if ((invalidation != nullptr) && (dataArchives != nullptr)) { if (supported != nullptr) { *supported = true; } - wchar_t buffer[1024]; - std::wstring iniFileName = ToWString(QDir::toNativeSeparators(getIniFileName())); - // epic ms fail: GetPrivateProfileString uses errno (for whatever reason) to signal a fail since the return value - // has a different meaning (number of bytes copied). HOWEVER, it will not set errno to 0 if NO error occured - errno = 0; - if (::GetPrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(), - L"", buffer, 1024, iniFileName.c_str()) == 0) { - if (errno != 0x02) { - if (supported != nullptr) { - *supported = false; - } - return false; - } else { - QString errorMessage = tr("failed to parse ini file (%1)").arg(ToQString(iniFileName)); - throw windows_error(errorMessage.toUtf8().constData()); - } - } - QStringList archives = ToQString(buffer).split(','); - for (int i = 0; i < archives.count(); ++i) { - QString bsaName = archives.at(i).trimmed(); - if (GameInfo::instance().isInvalidationBSA(ToWString(bsaName))) { + for (const QString &archive : dataArchives->archives(this)) { + if (invalidation->isInvalidationBSA(archive)) { return true; } } + return false; } else { *supported = false; } @@ -626,85 +616,26 @@ bool Profile::invalidationActive(bool *supported) const } -void Profile::deactivateInvalidation() const +void Profile::deactivateInvalidation() { - if (GameInfo::instance().requiresBSAInvalidation()) { - wchar_t buffer[1024]; - std::wstring iniFileName = ToWString(QDir::toNativeSeparators(getIniFileName())); - errno = 0; - if (::GetPrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(), - L"", buffer, 1024, iniFileName.c_str()) == 0) { - if (errno == 0x02) { - QString errorMessage = tr("failed to parse ini file (%1): %2").arg(QDir::toNativeSeparators(getIniFileName())).arg(::GetLastError()); - throw windows_error(errorMessage.toUtf8().constData()); - } else { - return; - } - } - QStringList archives = ToQString(buffer).split(", "); - - for (int i = 0; i < archives.count();) { - QString bsaName = archives.at(i).trimmed(); - if (GameInfo::instance().isInvalidationBSA(ToWString(bsaName))) { - archives.removeAt(i); - } else { - ++i; - } - } + IPluginGame *gamePlugin = qApp->property("managed_game").value(); - // just to be safe... - ::SetFileAttributesW(iniFileName.c_str(), FILE_ATTRIBUTE_NORMAL); + BSAInvalidation *invalidation = gamePlugin->feature(); - if (!::WritePrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(), - ToWString(archives.join(", ").toUtf8()).c_str(), iniFileName.c_str()) || - !::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", iniFileName.c_str()) || - !::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"ArchiveInvalidation.txt", iniFileName.c_str())) { - QString errorMessage = tr("failed to modify \"%1\"").arg(ToQString(iniFileName)); - throw windows_error(errorMessage.toUtf8().constData()); - } + if (invalidation != nullptr) { + invalidation->deactivate(this); } } -void Profile::activateInvalidation(const QString& dataDirectory) const +void Profile::activateInvalidation() { - if (GameInfo::instance().requiresBSAInvalidation()) { - wchar_t buffer[1024]; - std::wstring iniFileName = ToWString(QDir::toNativeSeparators(getIniFileName())); - errno = 0; - if (::GetPrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(), - L"", buffer, 1024, iniFileName.c_str()) == 0) { - if (errno == 0x02) { - throw windows_error("failed to parse ini file"); - } else { - // ignore. shouldn't have gotten here anyway - return; - } - } - QStringList archives = ToQString(buffer).split(", "); - - QString invalidationBSA = ToQString(GameInfo::instance().getInvalidationBSA()); + IPluginGame *gamePlugin = qApp->property("managed_game").value(); - if (!archives.contains(invalidationBSA)) { - archives.insert(0, invalidationBSA); - } - - // just to be safe... - ::SetFileAttributesW(iniFileName.c_str(), FILE_ATTRIBUTE_NORMAL); - - if (!::WritePrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(), - ToWString(archives.join(", ").toUtf8()).c_str(), iniFileName.c_str()) || - !::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"1", iniFileName.c_str()) || - !::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"", iniFileName.c_str())) { - QString errorMessage = tr("failed to modify \"%1\"").arg(ToQString(iniFileName)); - throw windows_error(errorMessage.toUtf8().constData()); - } + BSAInvalidation *invalidation = gamePlugin->feature(); - QString bsaFile = dataDirectory + "/" + invalidationBSA; - if (!QFile::exists(bsaFile)) { - DummyBSA bsa; - bsa.write(bsaFile); - } + if (invalidation != nullptr) { + invalidation->activate(this); } } @@ -784,7 +715,7 @@ QString Profile::getProfileTweaks() const return QDir::cleanPath(m_Directory.absoluteFilePath(ToQString(AppConfig::profileTweakIni()))); } -QString Profile::getPath() const +QString Profile::absolutePath() const { return QDir::cleanPath(m_Directory.absolutePath()); } @@ -792,6 +723,7 @@ QString Profile::getPath() const void Profile::rename(const QString &newName) { QDir profileDir(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::profilesPath())); - profileDir.rename(getName(), newName); + profileDir.rename(name(), newName); m_Directory = profileDir.absoluteFilePath(newName); } + diff --git a/src/profile.h b/src/profile.h index 34efd4b2..5eaa1ea1 100644 --- a/src/profile.h +++ b/src/profile.h @@ -22,7 +22,7 @@ along with Mod Organizer. If not, see . #include "modinfo.h" - +#include #include #include #include @@ -38,7 +38,7 @@ namespace MOBase { /** * @brief represents a profile **/ -class Profile : public QObject +class Profile : public QObject, public MOBase::IProfile { Q_OBJECT @@ -112,7 +112,7 @@ public: /** * @brief deactivate archive invalidation if it was active **/ - void deactivateInvalidation() const; + void deactivateInvalidation(); /** * @brief activate archive invalidation @@ -121,7 +121,7 @@ public: * @todo passing the data directory as a parameter is useless, the function should * be able to query it from GameInfo **/ - void activateInvalidation(const QString &dataDirectory) const; + void activateInvalidation(); /** * @return true if this profile uses local save games @@ -139,7 +139,7 @@ public: /** * @return name of the profile (this is identical to its directory name) **/ - QString getName() const { return m_Directory.dirName(); } + QString name() const { return m_Directory.dirName(); } /** * @return the path of the plugins file in this profile @@ -188,7 +188,7 @@ public: /** * @return path to this profile **/ - QString getPath() const; + QString absolutePath() const; void rename(const QString &newName); @@ -315,12 +315,15 @@ private: QDir m_Directory; + MOBase::IPluginGame *m_GamePlugin; + mutable QByteArray m_LastModlistHash; std::vector m_ModStatus; std::vector m_ModIndexByPriority; unsigned int m_NumRegularMods; QTimer *m_SaveTimer; + }; Q_DECLARE_METATYPE(Profile) diff --git a/src/profilesdialog.cpp b/src/profilesdialog.cpp index c6731041..44ee96e9 100644 --- a/src/profilesdialog.cpp +++ b/src/profilesdialog.cpp @@ -24,7 +24,9 @@ along with Mod Organizer. If not, see . #include "transfersavesdialog.h" #include "profileinputdialog.h" #include "mainwindow.h" -#include +#include "aboutdialog.h" +#include +#include #include #include #include @@ -40,10 +42,9 @@ using namespace MOShared; Q_DECLARE_METATYPE(Profile::Ptr) -ProfilesDialog::ProfilesDialog(const QString &gamePath, MOBase::IPluginGame *gamePlugin, QWidget *parent) +ProfilesDialog::ProfilesDialog(const QString &gamePath, QWidget *parent) : TutorableDialog("Profiles", parent) , ui(new Ui::ProfilesDialog) - , m_GamePlugin(gamePlugin) , m_GamePath(gamePath) , m_FailState(false) { @@ -61,7 +62,11 @@ ProfilesDialog::ProfilesDialog(const QString &gamePath, MOBase::IPluginGame *gam } QCheckBox *invalidationBox = findChild("invalidationBox"); - if (!GameInfo::instance().requiresBSAInvalidation()) { + + IPluginGame *game = qApp->property("managed_game").value(); + BSAInvalidation *invalidation = game->feature(); + + if (invalidation == nullptr) { invalidationBox->setToolTip(tr("Archive invalidation isn't required for this game.")); invalidationBox->setEnabled(false); } @@ -97,7 +102,7 @@ void ProfilesDialog::addItem(const QString &name) QDir profileDir(name); QListWidgetItem *newItem = new QListWidgetItem(profileDir.dirName(), m_ProfilesList); try { - newItem->setData(Qt::UserRole, QVariant::fromValue(Profile::Ptr(new Profile(profileDir, m_GamePlugin)))); + newItem->setData(Qt::UserRole, QVariant::fromValue(Profile::Ptr(new Profile(profileDir, qApp->property("managed_game").value())))); m_FailState = false; } catch (const std::exception& e) { reportError(tr("failed to create profile: %1").arg(e.what())); @@ -109,7 +114,7 @@ void ProfilesDialog::createProfile(const QString &name, bool useDefaultSettings) try { QListWidget *profilesList = findChild("profilesList"); QListWidgetItem *newItem = new QListWidgetItem(name, profilesList); - newItem->setData(Qt::UserRole, QVariant::fromValue(Profile::Ptr(new Profile(name, m_GamePlugin, useDefaultSettings)))); + newItem->setData(Qt::UserRole, QVariant::fromValue(Profile::Ptr(new Profile(name, qApp->property("managed_game").value(), useDefaultSettings)))); profilesList->addItem(newItem); m_FailState = false; } catch (const std::exception&) { @@ -123,7 +128,7 @@ void ProfilesDialog::createProfile(const QString &name, const Profile &reference try { QListWidget *profilesList = findChild("profilesList"); QListWidgetItem *newItem = new QListWidgetItem(name, profilesList); - newItem->setData(Qt::UserRole, QVariant::fromValue(Profile::Ptr(Profile::createPtrFrom(name, reference, m_GamePlugin)))); + newItem->setData(Qt::UserRole, QVariant::fromValue(Profile::Ptr(Profile::createPtrFrom(name, reference, qApp->property("managed_game").value())))); profilesList->addItem(newItem); m_FailState = false; } catch (const std::exception&) { @@ -190,7 +195,7 @@ void ProfilesDialog::on_removeProfileButton_clicked() } else { // on destruction, the profile object would write the profile.ini file again, so // we have to get rid of the it before deleting the directory - profilePath = currentProfile->getPath(); + profilePath = currentProfile->absolutePath(); } QListWidgetItem* item = profilesList->takeItem(profilesList->currentRow()); if (item != nullptr) { @@ -216,7 +221,7 @@ void ProfilesDialog::on_renameButton_clicked() while (!valid) { bool ok = false; name = QInputDialog::getText(this, tr("Rename Profile"), tr("New Name"), - QLineEdit::Normal, currentProfile->getName(), + QLineEdit::Normal, currentProfile->name(), &ok); valid = fixDirectoryName(name); if (!ok) { @@ -249,7 +254,7 @@ void ProfilesDialog::on_invalidationBox_stateChanged(int state) if (state == Qt::Unchecked) { currentProfile->deactivateInvalidation(); } else { - currentProfile->activateInvalidation(m_GamePath + "/data"); + currentProfile->activateInvalidation(); } } catch (const std::exception &e) { reportError(tr("failed to change archive invalidation state: %1").arg(e.what())); @@ -318,6 +323,6 @@ void ProfilesDialog::on_localSavesBox_stateChanged(int state) void ProfilesDialog::on_transferButton_clicked() { const Profile::Ptr currentProfile = m_ProfilesList->currentItem()->data(Qt::UserRole).value(); - TransferSavesDialog transferDialog(*currentProfile, m_GamePlugin, this); + TransferSavesDialog transferDialog(*currentProfile, qApp->property("managed_game").value(), this); transferDialog.exec(); } diff --git a/src/profilesdialog.h b/src/profilesdialog.h index 18b3932f..5cb5a449 100644 --- a/src/profilesdialog.h +++ b/src/profilesdialog.h @@ -50,7 +50,7 @@ public: * @param parent parent widget * @todo the game path could be retrieved from GameInfo just as easily **/ - explicit ProfilesDialog(const QString &gamePath, MOBase::IPluginGame *gamePlugin, QWidget *parent = 0); + explicit ProfilesDialog(const QString &gamePath, QWidget *parent = 0); ~ProfilesDialog(); /** @@ -91,7 +91,6 @@ private slots: private: Ui::ProfilesDialog *ui; - MOBase::IPluginGame *m_GamePlugin; QString m_GamePath; QListWidget *m_ProfilesList; bool m_FailState; diff --git a/src/selectiondialog.cpp b/src/selectiondialog.cpp index 1b284928..aae95f56 100644 --- a/src/selectiondialog.cpp +++ b/src/selectiondialog.cpp @@ -22,8 +22,8 @@ along with Mod Organizer. If not, see . #include -SelectionDialog::SelectionDialog(const QString &description, QWidget *parent) - : QDialog(parent), ui(new Ui::SelectionDialog), m_Choice(nullptr), m_ValidateByData(false) +SelectionDialog::SelectionDialog(const QString &description, QWidget *parent, const QSize &iconSize) + : QDialog(parent), ui(new Ui::SelectionDialog), m_Choice(nullptr), m_ValidateByData(false), m_IconSize(iconSize) { ui->setupUi(this); @@ -35,10 +35,24 @@ SelectionDialog::~SelectionDialog() delete ui; } - void SelectionDialog::addChoice(const QString &buttonText, const QString &description, const QVariant &data) { - QCommandLinkButton *button = new QCommandLinkButton(buttonText, description, ui->buttonBox); + QAbstractButton *button = new QCommandLinkButton(buttonText, description, ui->buttonBox); + if (m_IconSize.isValid()) { + button->setIconSize(m_IconSize); + } + button->setProperty("data", data); + ui->buttonBox->addButton(button, QDialogButtonBox::AcceptRole); + if (data.isValid()) m_ValidateByData = true; +} + +void SelectionDialog::addChoice(const QIcon &icon, const QString &buttonText, const QString &description, const QVariant &data) +{ + QAbstractButton *button = new QCommandLinkButton(buttonText, description, ui->buttonBox); + if (m_IconSize.isValid()) { + button->setIconSize(m_IconSize); + } + button->setIcon(icon); button->setProperty("data", data); ui->buttonBox->addButton(button, QDialogButtonBox::AcceptRole); if (data.isValid()) m_ValidateByData = true; @@ -49,7 +63,6 @@ int SelectionDialog::numChoices() const return ui->buttonBox->findChildren(QString()).count(); } - QVariant SelectionDialog::getChoiceData() { return m_Choice->property("data"); diff --git a/src/selectiondialog.h b/src/selectiondialog.h index fe148859..43ba9767 100644 --- a/src/selectiondialog.h +++ b/src/selectiondialog.h @@ -33,7 +33,7 @@ class SelectionDialog : public QDialog public: - explicit SelectionDialog(const QString &description, QWidget *parent = 0); + explicit SelectionDialog(const QString &description, QWidget *parent = 0, const QSize &iconSize = QSize()); ~SelectionDialog(); @@ -46,6 +46,8 @@ public: */ void addChoice(const QString &buttonText, const QString &description, const QVariant &data); + void addChoice(const QIcon &icon, const QString &buttonText, const QString &description, const QVariant &data); + int numChoices() const; QVariant getChoiceData(); @@ -62,6 +64,7 @@ private: Ui::SelectionDialog *ui; QAbstractButton *m_Choice; bool m_ValidateByData; + QSize m_IconSize; }; diff --git a/src/shared/fallout3info.cpp b/src/shared/fallout3info.cpp index c8688cc4..37238a2a 100644 --- a/src/shared/fallout3info.cpp +++ b/src/shared/fallout3info.cpp @@ -42,11 +42,6 @@ bool Fallout3Info::identifyGame(const std::wstring &searchPath) FileExists(searchPath, L"FalloutLauncher.exe"); } -unsigned long Fallout3Info::getBSAVersion() -{ - return 0x68; -} - std::wstring Fallout3Info::getRegPathStatic() { HKEY key; @@ -67,37 +62,6 @@ std::wstring Fallout3Info::getRegPathStatic() } } -std::wstring Fallout3Info::getInvalidationBSA() -{ - return L"Fallout - Invalidation.bsa"; -} - -bool Fallout3Info::isInvalidationBSA(const std::wstring &bsaName) -{ - static LPCWSTR invalidation[] = { L"Fallout - AI!.bsa", L"Fallout - Invalidation.bsa", nullptr }; - - for (int i = 0; invalidation[i] != nullptr; ++i) { - if (wcscmp(bsaName.c_str(), invalidation[i]) == 0) { - return true; - } - } - return false; -} - -std::vector Fallout3Info::getPrimaryPlugins() -{ - return boost::assign::list_of(L"fallout3.esm"); -} - -std::vector Fallout3Info::getVanillaBSAs() -{ - return boost::assign::list_of (L"Fallout - Textures.bsa") - (L"Fallout - Meshes.bsa") - (L"Fallout - Voices.bsa") - (L"Fallout - Sound.bsa") - (L"Fallout - MenuVoices.bsa") - (L"Fallout - Misc.bsa"); -} std::vector Fallout3Info::getDLCPlugins() { @@ -125,20 +89,14 @@ std::wstring Fallout3Info::getReferenceDataFile() } -std::wstring Fallout3Info::getOMODExt() -{ - return L"fomod"; -} + std::vector Fallout3Info::getSteamVariants() const { return boost::assign::list_of(L"Regular")(L"Game Of The Year"); } -std::wstring Fallout3Info::getSEName() -{ - return L"fose"; -} + std::wstring Fallout3Info::getNexusPage(bool nmmScheme) { diff --git a/src/shared/fallout3info.h b/src/shared/fallout3info.h index 6a211d4f..1f3a381d 100644 --- a/src/shared/fallout3info.h +++ b/src/shared/fallout3info.h @@ -35,8 +35,6 @@ public: virtual ~Fallout3Info() {} - virtual unsigned long getBSAVersion(); - static std::wstring getRegPathStatic(); virtual std::wstring getRegPath() { return getRegPathStatic(); } virtual std::wstring getBinaryName() { return L"Fallout3.exe"; } @@ -45,14 +43,38 @@ public: virtual std::wstring getGameName() const { return L"Fallout 3"; } virtual std::wstring getGameShortName() const { return L"Fallout3"; } - - virtual std::wstring getInvalidationBSA(); - - virtual bool isInvalidationBSA(const std::wstring &bsaName); - - virtual std::vector getPrimaryPlugins(); - - virtual std::vector getVanillaBSAs(); +/* + virtual std::wstring getInvalidationBSA() + { + return L"Fallout - Invalidation.bsa"; + } + + virtual bool isInvalidationBSA(const std::wstring &bsaName) + { + static LPCWSTR invalidation[] = { L"Fallout - AI!.bsa", L"Fallout - Invalidation.bsa", nullptr }; + + for (int i = 0; invalidation[i] != nullptr; ++i) { + if (wcscmp(bsaName.c_str(), invalidation[i]) == 0) { + return true; + } + } + return false; + } + + virtual std::vector getVanillaBSAs() + { + return boost::assign::list_of (L"Fallout - Textures.bsa") + (L"Fallout - Meshes.bsa") + (L"Fallout - Voices.bsa") + (L"Fallout - Sound.bsa") + (L"Fallout - MenuVoices.bsa") + (L"Fallout - Misc.bsa"); + } + + virtual std::vector getPrimaryPlugins() + { + return boost::assign::list_of(L"fallout3.esm"); + }*/ virtual std::vector getDLCPlugins(); virtual std::vector getSavegameAttachmentExtensions(); @@ -60,12 +82,9 @@ public: virtual std::vector getIniFileNames(); virtual std::wstring getReferenceDataFile(); - virtual std::wstring getOMODExt(); virtual std::vector getSteamVariants() const; - virtual std::wstring getSEName(); - virtual std::wstring getNexusPage(bool nmmScheme = true); static std::wstring getNexusInfoUrlStatic(); virtual std::wstring getNexusInfoUrl() { return getNexusInfoUrlStatic(); } diff --git a/src/shared/falloutnvinfo.cpp b/src/shared/falloutnvinfo.cpp index 8e701887..1203bd25 100644 --- a/src/shared/falloutnvinfo.cpp +++ b/src/shared/falloutnvinfo.cpp @@ -43,11 +43,6 @@ bool FalloutNVInfo::identifyGame(const std::wstring &searchPath) FileExists(searchPath, L"FalloutNVLauncher.exe"); } -unsigned long FalloutNVInfo::getBSAVersion() -{ - return 0x68; -} - std::wstring FalloutNVInfo::getRegPathStatic() { HKEY key; @@ -68,38 +63,6 @@ std::wstring FalloutNVInfo::getRegPathStatic() } } -std::wstring FalloutNVInfo::getInvalidationBSA() -{ - return L"Fallout - Invalidation.bsa"; -} - -bool FalloutNVInfo::isInvalidationBSA(const std::wstring &bsaName) -{ - static LPCWSTR invalidation[] = { L"Fallout - AI!.bsa", L"Fallout - Invalidation.bsa", nullptr }; - - for (int i = 0; invalidation[i] != nullptr; ++i) { - if (wcscmp(bsaName.c_str(), invalidation[i]) == 0) { - return true; - } - } - return false; -} - -std::vector FalloutNVInfo::getPrimaryPlugins() -{ - return boost::assign::list_of(L"falloutnv.esm"); -} - -std::vector FalloutNVInfo::getVanillaBSAs() -{ - return boost::assign::list_of (L"Fallout - Textures.bsa") - (L"Fallout - Textures2.bsa") - (L"Fallout - Meshes.bsa") - (L"Fallout - Voices1.bsa") - (L"Fallout - Sound.bsa") - (L"Fallout - Misc.bsa"); -} - std::vector FalloutNVInfo::getDLCPlugins() { return boost::assign::list_of (L"DeadMoney.esm") @@ -129,19 +92,6 @@ std::wstring FalloutNVInfo::getReferenceDataFile() return L"Fallout - Meshes.bsa"; } - -std::wstring FalloutNVInfo::getOMODExt() -{ - return L"fomod"; -} - - -std::wstring FalloutNVInfo::getSEName() -{ - return L"nvse"; -} - - std::wstring FalloutNVInfo::getNexusPage(bool nmmScheme) { if (nmmScheme) { @@ -176,17 +126,4 @@ bool FalloutNVInfo::rerouteToProfile(const wchar_t *fileName, const wchar_t*) return false; } -/* -std::vector FalloutNVInfo::getExecutables() -{ - std::vector result; - result.push_back(ExecutableInfo(L"NVSE", L"nvse_loader.exe", L"", L"", DEFAULT_CLOSE)); - result.push_back(ExecutableInfo(L"New Vegas", L"falloutnv.exe", L"", L"", DEFAULT_CLOSE)); - result.push_back(ExecutableInfo(L"Fallout Mod Manager", L"fomm/fomm.exe", L"", L"", DEFAULT_CLOSE)); - result.push_back(ExecutableInfo(L"Construction Kit", L"geck.exe", L"", L"", DEFAULT_CLOSE)); - result.push_back(ExecutableInfo(L"Fallout Launcher", L"FalloutNVLauncher.exe", L"", L"", DEFAULT_CLOSE)); - result.push_back(ExecutableInfo(L"BOSS", L"BOSS/BOSS.exe", L"", L"", NEVER_CLOSE)); - - return result; -}*/ } // namespace MOShared diff --git a/src/shared/falloutnvinfo.h b/src/shared/falloutnvinfo.h index 513b7218..e1a614d2 100644 --- a/src/shared/falloutnvinfo.h +++ b/src/shared/falloutnvinfo.h @@ -35,8 +35,6 @@ public: virtual ~FalloutNVInfo() {} - virtual unsigned long getBSAVersion(); - static std::wstring getRegPathStatic(); virtual std::wstring getRegPath() { return getRegPathStatic(); } virtual std::wstring getBinaryName() { return L"FalloutNV.exe"; } @@ -48,13 +46,37 @@ public: // virtual bool requiresSteam() const { return true; } - virtual std::wstring getInvalidationBSA(); - - virtual bool isInvalidationBSA(const std::wstring &bsaName); - - virtual std::vector getPrimaryPlugins(); - - virtual std::vector getVanillaBSAs(); +/* virtual std::wstring getInvalidationBSA() + { + return L"Fallout - Invalidation.bsa"; + } + + virtual bool isInvalidationBSA(const std::wstring &bsaName) + { + static LPCWSTR invalidation[] = { L"Fallout - AI!.bsa", L"Fallout - Invalidation.bsa", nullptr }; + + for (int i = 0; invalidation[i] != nullptr; ++i) { + if (wcscmp(bsaName.c_str(), invalidation[i]) == 0) { + return true; + } + } + return false; + } + + virtual std::vector getVanillaBSAs() + { + return boost::assign::list_of (L"Fallout - Textures.bsa") + (L"Fallout - Textures2.bsa") + (L"Fallout - Meshes.bsa") + (L"Fallout - Voices1.bsa") + (L"Fallout - Sound.bsa") + (L"Fallout - Misc.bsa"); + } + + virtual std::vector getPrimaryPlugins() + { + return boost::assign::list_of(L"falloutnv.esm"); + }*/ virtual std::vector getDLCPlugins(); virtual std::vector getSavegameAttachmentExtensions(); @@ -62,9 +84,6 @@ public: virtual std::vector getIniFileNames(); virtual std::wstring getReferenceDataFile(); - virtual std::wstring getOMODExt(); - - virtual std::wstring getSEName(); virtual std::wstring getNexusPage(bool nmmScheme = true); static std::wstring getNexusInfoUrlStatic(); diff --git a/src/shared/gameinfo.h b/src/shared/gameinfo.h index dbb935f6..77ed4d3c 100644 --- a/src/shared/gameinfo.h +++ b/src/shared/gameinfo.h @@ -28,32 +28,7 @@ along with Mod Organizer. If not, see . #include namespace MOShared { -/* -enum CloseMOStyle { - DEFAULT_CLOSE, - DEFAULT_STAY, - NEVER_CLOSE -}; -struct ExecutableInfo { - - ExecutableInfo(const std::wstring &aTitle, const std::wstring &aBinary, - const std::wstring &aArguments, const std::wstring &aWorkingDirectory, CloseMOStyle aCloseMO) - : title(aTitle), binary(aBinary), arguments(aArguments), workingDirectory(aWorkingDirectory), - closeMO(aCloseMO), steamAppID(L"") {} - ExecutableInfo(const std::wstring &aTitle, const std::wstring &aBinary, - const std::wstring &aArguments, const std::wstring &aWorkingDirectory, - CloseMOStyle aCloseMO, const std::wstring &aSteamAppID) - : title(aTitle), binary(aBinary), arguments(aArguments), workingDirectory(aWorkingDirectory), - closeMO(aCloseMO), steamAppID(aSteamAppID) {} - std::wstring title; - std::wstring binary; - std::wstring arguments; - std::wstring workingDirectory; - CloseMOStyle closeMO; - std::wstring steamAppID; -}; -*/ /** Class to manage information that depends on the used game type. The intention is to keep @@ -86,8 +61,6 @@ public: virtual std::wstring getRegPath() = 0; virtual std::wstring getBinaryName() = 0; - virtual unsigned long getBSAVersion() = 0; - virtual GameInfo::Type getType() = 0; virtual std::wstring getGameName() const = 0; @@ -98,30 +71,8 @@ public: virtual LoadOrderMechanism getLoadOrderMechanism() const { return TYPE_FILETIME; } virtual std::wstring getGameDirectory() const; - // get absolute path to the directory where omo stores its mods -/* virtual std::wstring getModsDir() const; - // get absolute path to the directory where omo stores its profiles - virtual std::wstring getProfilesDir() const; - - virtual std::wstring getIniFilename() const; - virtual std::wstring getOverwriteDir() const; - virtual std::wstring getLogDir() const; - virtual std::wstring getLootDir() const; - virtual std::wstring getTutorialDir() const;*/ - - virtual bool requiresBSAInvalidation() const { return true; } - virtual bool requiresSteam() const; - - virtual std::wstring getInvalidationBSA() = 0; - virtual bool isInvalidationBSA(const std::wstring &bsaName) = 0; - - // the key in the game's ini-file that defines the list of bsas to load - virtual std::wstring archiveListKey() = 0; - - virtual std::vector getPrimaryPlugins() = 0; - - virtual std::vector getVanillaBSAs() = 0; + virtual bool requiresSteam() const; // get a list of file extensions for additional files belonging to a save game virtual std::vector getSavegameAttachmentExtensions() = 0; @@ -134,12 +85,8 @@ public: virtual std::wstring getReferenceDataFile() = 0; - virtual std::wstring getOMODExt() = 0; - virtual std::vector getSteamVariants() const; - virtual std::wstring getSEName() = 0; - virtual std::wstring getNexusPage(bool nmmScheme = true) = 0; virtual std::wstring getNexusInfoUrl() = 0; virtual int getNexusModID() = 0; diff --git a/src/shared/oblivioninfo.cpp b/src/shared/oblivioninfo.cpp index c945dcf4..16748f58 100644 --- a/src/shared/oblivioninfo.cpp +++ b/src/shared/oblivioninfo.cpp @@ -43,11 +43,6 @@ bool OblivionInfo::identifyGame(const std::wstring &searchPath) FileExists(searchPath, L"OblivionLauncher.exe"); } -unsigned long OblivionInfo::getBSAVersion() -{ - return 0x67; -} - std::wstring OblivionInfo::getRegPathStatic() { HKEY key; @@ -68,39 +63,14 @@ std::wstring OblivionInfo::getRegPathStatic() } } -std::wstring OblivionInfo::getInvalidationBSA() -{ - return L"Oblivion - Invalidation.bsa"; -} -bool OblivionInfo::isInvalidationBSA(const std::wstring &bsaName) -{ - static LPCWSTR invalidation[] = { L"Oblivion - Invalidation.bsa", L"ArchiveInvalidationInvalidated!.bsa", - L"BSARedirection.bsa", nullptr }; - for (int i = 0; invalidation[i] != nullptr; ++i) { - if (wcscmp(bsaName.c_str(), invalidation[i]) == 0) { - return true; - } - } - return false; -} -std::vector OblivionInfo::getPrimaryPlugins() -{ - return boost::assign::list_of(L"oblivion.esm"); -} -std::vector OblivionInfo::getVanillaBSAs() -{ - return boost::assign::list_of(L"Oblivion - Meshes.bsa") - (L"Oblivion - Textures - Compressed.bsa") - (L"Oblivion - Sounds.bsa") - (L"Oblivion - Voices1.bsa") - (L"Oblivion - Voices2.bsa") - (L"Oblivion - Misc.bsa"); -} + + + std::vector OblivionInfo::getDLCPlugins() @@ -131,10 +101,7 @@ std::vector OblivionInfo::getIniFileNames() } -std::wstring OblivionInfo::getSEName() -{ - return L"obse"; -} + std::wstring OblivionInfo::getNexusPage(bool nmmScheme) @@ -175,11 +142,4 @@ std::wstring OblivionInfo::getReferenceDataFile() return L"Oblivion - Meshes.bsa"; } - -std::wstring OblivionInfo::getOMODExt() -{ - return L"omod"; -} - - } // namespace MOShared diff --git a/src/shared/oblivioninfo.h b/src/shared/oblivioninfo.h index a93f510e..87ba26ff 100644 --- a/src/shared/oblivioninfo.h +++ b/src/shared/oblivioninfo.h @@ -33,8 +33,6 @@ public: virtual ~OblivionInfo() {} - virtual unsigned long getBSAVersion(); - static std::wstring getRegPathStatic(); virtual std::wstring getRegPath() { return getRegPathStatic(); } virtual std::wstring getBinaryName() { return L"Oblivion.exe"; } @@ -43,14 +41,40 @@ public: virtual std::wstring getGameName() const { return L"Oblivion"; } virtual std::wstring getGameShortName() const { return L"Oblivion"; } +/* + virtual std::wstring getInvalidationBSA() + { + return L"Oblivion - Invalidation.bsa"; + } + + virtual bool isInvalidationBSA(const std::wstring &bsaName) + { + static LPCWSTR invalidation[] = { L"Oblivion - Invalidation.bsa", L"ArchiveInvalidationInvalidated!.bsa", + L"BSARedirection.bsa", nullptr }; + + for (int i = 0; invalidation[i] != nullptr; ++i) { + if (wcscmp(bsaName.c_str(), invalidation[i]) == 0) { + return true; + } + } + return false; + } + + virtual std::vector getVanillaBSAs() + { + return boost::assign::list_of(L"Oblivion - Meshes.bsa") + (L"Oblivion - Textures - Compressed.bsa") + (L"Oblivion - Sounds.bsa") + (L"Oblivion - Voices1.bsa") + (L"Oblivion - Voices2.bsa") + (L"Oblivion - Misc.bsa"); + } + + virtual std::vector getPrimaryPlugins() + { + return boost::assign::list_of(L"oblivion.esm"); + }*/ - virtual std::wstring getInvalidationBSA(); - - virtual bool isInvalidationBSA(const std::wstring &bsaName); - - virtual std::vector getPrimaryPlugins(); - - virtual std::vector getVanillaBSAs(); virtual std::vector getDLCPlugins(); virtual std::vector getSavegameAttachmentExtensions(); @@ -58,9 +82,6 @@ public: virtual std::vector getIniFileNames(); virtual std::wstring getReferenceDataFile(); - virtual std::wstring getOMODExt(); - - virtual std::wstring getSEName(); virtual std::wstring getNexusPage(bool nmmScheme = true); static std::wstring getNexusInfoUrlStatic(); diff --git a/src/shared/skyriminfo.cpp b/src/shared/skyriminfo.cpp index feaf88a3..f66fcef4 100644 --- a/src/shared/skyriminfo.cpp +++ b/src/shared/skyriminfo.cpp @@ -50,10 +50,7 @@ bool SkyrimInfo::identifyGame(const std::wstring &searchPath) FileExists(searchPath, L"SkyrimLauncher.exe"); } -unsigned long SkyrimInfo::getBSAVersion() -{ - return 0x68; -} + std::wstring SkyrimInfo::getRegPathStatic() @@ -76,25 +73,6 @@ std::wstring SkyrimInfo::getRegPathStatic() } } - -std::wstring SkyrimInfo::getInvalidationBSA() -{ - return L"Skyrim - Invalidation.bsa"; -} - -bool SkyrimInfo::isInvalidationBSA(const std::wstring &bsaName) -{ - static LPCWSTR invalidation[] = { L"Skyrim - Invalidation.bsa", nullptr }; - - for (int i = 0; invalidation[i] != nullptr; ++i) { - if (wcscmp(bsaName.c_str(), invalidation[i]) == 0) { - return true; - } - } - return false; -} - - GameInfo::LoadOrderMechanism SkyrimInfo::getLoadOrderMechanism() const { std::wstring fileName = getGameDirectory() + L"\\TESV.exe"; @@ -113,27 +91,6 @@ GameInfo::LoadOrderMechanism SkyrimInfo::getLoadOrderMechanism() const } } -std::vector SkyrimInfo::getPrimaryPlugins() -{ - return boost::assign::list_of(L"skyrim.esm")(L"update.esm"); -} - -std::vector SkyrimInfo::getVanillaBSAs() -{ - return boost::assign::list_of(L"Skyrim - Misc.bsa") - (L"Skyrim - Shaders.bsa") - (L"Skyrim - Textures.bsa") - (L"HighResTexturePack01.bsa") - (L"HighResTexturePack02.bsa") - (L"HighResTexturePack03.bsa") - (L"Skyrim - Interface.bsa") - (L"Skyrim - Animations.bsa") - (L"Skyrim - Meshes.bsa") - (L"Skyrim - Sounds.bsa") - (L"Skyrim - Voices.bsa") - (L"Skyrim - VoicesExtra.bsa"); -} - std::vector SkyrimInfo::getDLCPlugins() { return boost::assign::list_of (L"Dawnguard.esm") @@ -161,17 +118,6 @@ std::wstring SkyrimInfo::getReferenceDataFile() } -std::wstring SkyrimInfo::getOMODExt() -{ - return L"fomod"; -} - -std::wstring SkyrimInfo::getSEName() -{ - return L"skse"; -} - - std::wstring SkyrimInfo::getNexusPage(bool nmmScheme) { if (nmmScheme) { diff --git a/src/shared/skyriminfo.h b/src/shared/skyriminfo.h index bf08fb25..5951f910 100644 --- a/src/shared/skyriminfo.h +++ b/src/shared/skyriminfo.h @@ -35,8 +35,6 @@ public: virtual ~SkyrimInfo() {} - virtual unsigned long getBSAVersion(); - static std::wstring getRegPathStatic(); virtual std::wstring getRegPath() { return getRegPathStatic(); } virtual std::wstring getBinaryName() { return L"TESV.exe"; } @@ -48,15 +46,6 @@ public: virtual LoadOrderMechanism getLoadOrderMechanism() const; - virtual bool requiresBSAInvalidation() const { return true; } - - virtual std::wstring getInvalidationBSA(); - - virtual bool isInvalidationBSA(const std::wstring &bsaName); - - virtual std::vector getPrimaryPlugins(); - - virtual std::vector getVanillaBSAs(); virtual std::vector getDLCPlugins(); virtual std::vector getSavegameAttachmentExtensions(); @@ -65,9 +54,6 @@ public: virtual std::vector getIniFileNames(); virtual std::wstring getReferenceDataFile(); - virtual std::wstring getOMODExt(); - - virtual std::wstring getSEName(); virtual std::wstring getNexusPage(bool nmmScheme = true); @@ -80,8 +66,6 @@ public: virtual bool rerouteToProfile(const wchar_t *fileName, const wchar_t *fullPath); - virtual std::wstring archiveListKey() { return L"SResourceArchiveList"; } - private: SkyrimInfo(const std::wstring &moDirectory, const std::wstring &moDataDirectory, const std::wstring &gameDirectory); -- cgit v1.3.1