From 7b087f8f9d94b3758b3dad8d29670cd73d058510 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 6 Dec 2015 21:10:37 +0000 Subject: [PATCH 1/8] Facepalm moments - realised gameinfo init call is no longer needed. Removed all references --- src/main.cpp | 4 ---- src/nxmaccessmanager.cpp | 1 - src/profile.h | 4 ---- src/profilesdialog.h | 1 - src/settings.cpp | 1 - 5 files changed, 11 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 353e7202..3469e9c3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,7 +35,6 @@ along with Mod Organizer. If not, see . #include #include "modlist.h" #include "profile.h" -#include "gameinfo.h" #include "spawn.h" #include "executableslist.h" #include "singleinstance.h" @@ -569,9 +568,6 @@ int main(int argc, char *argv[]) organizer.setManagedGame(game); - //*sigh just for making it work - GameInfo::init(application.applicationDirPath().toStdWString(), game->gameDirectory().absolutePath().toStdWString()); - organizer.createDefaultProfile(); //See the pragma - we apparently don't use this so not sure why we check it diff --git a/src/nxmaccessmanager.cpp b/src/nxmaccessmanager.cpp index 7d0dacc2..616b3806 100644 --- a/src/nxmaccessmanager.cpp +++ b/src/nxmaccessmanager.cpp @@ -26,7 +26,6 @@ along with Mod Organizer. If not, see . #include "selfupdater.h" #include "persistentcookiejar.h" #include "settings.h" -#include #include #include #include diff --git a/src/profile.h b/src/profile.h index b306e0c5..e33ac674 100644 --- a/src/profile.h +++ b/src/profile.h @@ -102,10 +102,6 @@ class Profile : public QObject, public MOBase::IProfile /** * @brief activate archive invalidation - * - * @param dataDirectory data directory of the game - * @todo passing the data directory as a parameter is useless, the function should - * be able to query it from GameInfo **/ void activateInvalidation(); diff --git a/src/profilesdialog.h b/src/profilesdialog.h index 26476883..073d92b7 100644 --- a/src/profilesdialog.h +++ b/src/profilesdialog.h @@ -48,7 +48,6 @@ class ProfilesDialog : public MOBase::TutorableDialog * * @param profileName currently enabled profile * @param parent parent widget - * @todo the game path could be retrieved from GameInfo just as easily **/ explicit ProfilesDialog(const QString &profileName, MOBase::IPluginGame const *game, QWidget *parent = 0); ~ProfilesDialog(); diff --git a/src/settings.cpp b/src/settings.cpp index 479dd3ab..d493be1d 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -22,7 +22,6 @@ along with Mod Organizer. If not, see . #include "settingsdialog.h" #include "utility.h" #include "helper.h" -#include #include #include #include From 4a8c7306be06ed82df789ce544dcb73a407d4502 Mon Sep 17 00:00:00 2001 From: ThosRTanner Date: Sun, 6 Dec 2015 22:12:39 +0000 Subject: [PATCH 2/8] Adding fallout4 to the list --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index e985a130..99ee7eb7 100644 --- a/readme.md +++ b/readme.md @@ -32,6 +32,7 @@ Here is a complete list: * https://github.com/TanninOne/modorganizer-game_skyrim * https://github.com/TanninOne/modorganizer-game_oblivion * https://github.com/TanninOne/modorganizer-game_fallout3 +* https://github.com/TanninOne/modorganizer-game_fallout4 * https://github.com/TanninOne/modorganizer-game_falloutnv * https://github.com/TanninOne/modorganizer-game_gamebryo * https://github.com/TanninOne/modorganizer-game_features From a3a4d5441daf16de8c17a1e35857c48307cfa281 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 12 Dec 2015 11:51:05 +0000 Subject: [PATCH 3/8] Full details from include what you use for qt creator 'issue' box --- massage_messages.py | 85 +++++++++++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 33 deletions(-) diff --git a/massage_messages.py b/massage_messages.py index 249068ba..5657f6b4 100644 --- a/massage_messages.py +++ b/massage_messages.py @@ -28,11 +28,14 @@ class QWidget; namespace Ui { class AboutDialog; } // lines 31-31 --- """ + removing = None +includes = dict() -includes = dict +adding = None +added = dict() -foundline = 0 +foundline = None errors = False @@ -45,34 +48,49 @@ def process_next_line(line, outfile): global includes global foundline global errors + global added + global adding line = line.rstrip() print >> outfile, line - if removing: - if line == '': - removing = None - print - return + + if line.endswith(' should remove these lines:'): + adding = None + removing = (line.split(' '))[0] + elif line.endswith(' should add these lines:'): + removing = None + adding = (line.split(' '))[0] + elif line == '' or line.startswith(' the full include-list'): + adding = None + removing = None + elif adding: + m = re.match(r'.*class (.*);', line) + if m: + added[m.group(1)] = (adding, line) else: - # Really we should stash these so that if we get a 'class xxx' in - # the add lines we can print it here. also we could do the case - # fixing. - m = re.match(r'- #include [<"](.*)[">] +// lines (.*)-', line) + added[line] = (adding, line) + elif removing: + # Really we should stash these so that if we get a 'class xxx' in + # the add lines we can print it here. also we could do the case + # fixing. + m = re.match(r'- #include [<"](.*)[">] +// lines (.*)-', line) + if m: + foundline = m.group(2) + print '%s(%s) : warning I0001: Unnecessary include of %s' %\ + (removing, m.group(2), m.group(1)) + if m.group(1) in added: + print ' %s(%s) : note: Use forward reference %s' % ( + removing, m.group(2), added[m.group(1)][1]) + del added[m.group(1)] + else: + m = re.match(r'- (.*) +// lines (.*)-', line) if m: - # If there is an added line with the same class, print it here - print '%s(%s) : warning I0001: Unnecessary include of %s' %\ - (removing, m.group(2), m.group(1)) - foundline = m.group(1) + foundline = m.group(2) + print '%s(%s) : warning I0002: '\ + 'Unnecessary forward ref of %s' %\ + (removing, m.group(2), m.group(1)) else: - m = re.match(r'- (.*) +// lines (.*)-', line) - if m: - print '%s(%s) : warning I0002: '\ - 'Unnecessary forward ref of %s' %\ - (removing, m.group(2), m.group(1)) - foundline = m.group(1) - else: - print '********* I got confused **********' - - if line.startswith('In file included from'): + print '********* I got confused **********' + elif line.startswith('In file included from'): line = re.sub(r'^(In file included from)(.*):(\d+):', r' \2(\3) : \1 here', line) @@ -88,14 +106,6 @@ def process_next_line(line, outfile): errors = True print line - if line.endswith(' should remove these lines:'): - removing = (line.split(' '))[0] - elif line.endswith(' should add these lines:'): - adding = (line.split(' '))[0] - -# also process the other lines - - # added lines should come after the first entry with a line number. outfile = open(sys.argv[1], 'w') process = subprocess.Popen(sys.argv[2:], @@ -107,6 +117,15 @@ def process_next_line(line, outfile): if output: process_next_line(output, outfile) +# A note: We should probably do some work as we use the source code line for +# messages in include files... + +if foundline is None: + foundline = '1' +for add in added: + print '%s(%s) : warning I0003: Need to include %s' % ( + added[add][0], foundline, added[add][1]) + rc = process.poll() # The return code you get appears to be more to do with the amount of output # generated than any real error, so instead we should error if any ': error:' From c344714661a2404a54428439f0cf7dbb1573d01f Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 12 Dec 2015 12:35:14 +0000 Subject: [PATCH 4/8] And found it was unreadable so ordered things a bit and replaced 2 line 'could use forward reference' with 1 --- massage_messages.py | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/massage_messages.py b/massage_messages.py index 5657f6b4..d79f4cea 100644 --- a/massage_messages.py +++ b/massage_messages.py @@ -1,3 +1,5 @@ +from collections import defaultdict + import fileinput import re import subprocess @@ -39,6 +41,8 @@ class QWidget; errors = False +messages = defaultdict(list) + def process_next_line(line, outfile): """ Read a line of output/error from include-what-you use Turn clang errors into a form QT creator recognises @@ -75,19 +79,23 @@ def process_next_line(line, outfile): m = re.match(r'- #include [<"](.*)[">] +// lines (.*)-', line) if m: foundline = m.group(2) - print '%s(%s) : warning I0001: Unnecessary include of %s' %\ - (removing, m.group(2), m.group(1)) if m.group(1) in added: - print ' %s(%s) : note: Use forward reference %s' % ( - removing, m.group(2), added[m.group(1)][1]) + messages[removing].append( + '%s(%s) : warning I0004: Replace include of %s with ' + 'forward reference %s' % ( + removing, m.group(2), m.group(1), added[m.group(1)][1])) del added[m.group(1)] + else: + messages[removing].append( + '%s(%s) : warning I0001: Unnecessary include of %s' % ( + removing, m.group(2), m.group(1))) + else: m = re.match(r'- (.*) +// lines (.*)-', line) if m: - foundline = m.group(2) - print '%s(%s) : warning I0002: '\ - 'Unnecessary forward ref of %s' %\ - (removing, m.group(2), m.group(1)) + messages[removing].append( + '%s(%s) : warning I0002: Unnecessary forward ref of %s' % ( + removing, m.group(2), m.group(1))) else: print '********* I got confused **********' elif line.startswith('In file included from'): @@ -122,9 +130,15 @@ def process_next_line(line, outfile): if foundline is None: foundline = '1' + for add in added: - print '%s(%s) : warning I0003: Need to include %s' % ( - added[add][0], foundline, added[add][1]) + messages[added[add][0]].append( + '%s(%s) : warning I0003: Need to include %s' % ( + added[add][0], foundline, added[add][1])) + +for file in sorted(messages.keys(), reverse = True): + for line in messages[file]: + print line rc = process.poll() # The return code you get appears to be more to do with the amount of output From 2d43645b646df75cfe76eaa952e85ffcaff3951a Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 20 Dec 2015 22:25:11 +0000 Subject: [PATCH 5/8] Restore start download file method (2 of 3) --- src/downloadmanager.cpp | 5 ++--- src/downloadmanager.h | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index cbc1ba45..c551e590 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -1244,14 +1244,13 @@ int DownloadManager::startDownloadURLs(const QStringList &urls) return m_ActiveDownloads.size() - 1; } -/* This doesn't appear to be used by anything int DownloadManager::startDownloadNexusFile(int modID, int fileID) { int newID = m_ActiveDownloads.size(); - addNXMDownload(QString("nxm://%1/mods/%2/files/%3").arg(ToQString(MOShared::GameInfo::instance().getGameName())).arg(modID).arg(fileID)); + addNXMDownload(QString("nxm://%1/mods/%2/files/%3").arg(m_ManagedGame->getGameShortName()).arg(modID).arg(fileID)); return newID; } -*/ + QString DownloadManager::downloadPath(int id) { return getFilePath(id); diff --git a/src/downloadmanager.h b/src/downloadmanager.h index 54db4648..e63a0113 100644 --- a/src/downloadmanager.h +++ b/src/downloadmanager.h @@ -329,9 +329,9 @@ class DownloadManager : public MOBase::IDownloadManager virtual int startDownloadURLs(const QStringList &urls); - /* This doesn't appear to be used anywhere + virtual int startDownloadNexusFile(int modID, int fileID); - */ + virtual QString downloadPath(int id); /** From d4326250fb95a476e4262d8407f497f262f47599 Mon Sep 17 00:00:00 2001 From: TanninOne Date: Mon, 21 Dec 2015 15:11:55 +0100 Subject: [PATCH 6/8] Update readme.md --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index 99ee7eb7..9611ee40 100644 --- a/readme.md +++ b/readme.md @@ -39,3 +39,4 @@ Here is a complete list: * https://github.com/TanninOne/modorganizer-check_fnis * https://github.com/TanninOne/modorganizer-plugin_python * https://github.com/TanninOne/modorganizer-bsa_extractor +* https://github.com/TanninOne/usvfs From 1d1cd36957f27296194a4d66b49d601fdbba0ca2 Mon Sep 17 00:00:00 2001 From: TanninOne Date: Mon, 28 Dec 2015 13:50:20 +0100 Subject: [PATCH 7/8] slight fixes to transfer saves functionality --- src/transfersavesdialog.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/transfersavesdialog.cpp b/src/transfersavesdialog.cpp index f6ca27cd..838d12ce 100644 --- a/src/transfersavesdialog.cpp +++ b/src/transfersavesdialog.cpp @@ -157,7 +157,7 @@ void TransferSavesDialog::on_moveToLocalBtn_clicked() { QString selectedCharacter = ui->globalCharacterList->currentItem()->text(); if (QMessageBox::question(this, tr("Confirm"), - tr("Copy all save games of character \"%1\" to the profile?").arg(selectedCharacter), + tr("Move all save games of character \"%1\" to the profile?").arg(selectedCharacter), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { QString destination = m_Profile.absolutePath() + "/saves"; OverwriteMode overwriteMode = OVERWRITE_ASK; @@ -176,10 +176,11 @@ void TransferSavesDialog::on_moveToLocalBtn_clicked() continue; } } - if (!QFile::rename(fileInfo.absoluteFilePath(), destinationFile)) { - qCritical("failed to move %s to %s", + if (!shellMove(fileInfo.absoluteFilePath(), destinationFile)) { + qCritical("failed to move %s to %s: %lu", fileInfo.absoluteFilePath().toUtf8().constData(), - destinationFile.toUtf8().constData()); + destinationFile.toUtf8().constData(), + ::GetLastError()); } } } @@ -240,7 +241,7 @@ void TransferSavesDialog::on_moveToGlobalBtn_clicked() continue; } } - if (!QFile::rename(fileInfo.absoluteFilePath(), destinationFile)) { + if (!shellMove(fileInfo.absoluteFilePath(), destinationFile)) { qCritical("failed to move %s to %s", fileInfo.absoluteFilePath().toUtf8().constData(), destinationFile.toUtf8().constData()); @@ -279,7 +280,7 @@ void TransferSavesDialog::on_copyToGlobalBtn_clicked() continue; } } - if (!QFile::copy(fileInfo.absoluteFilePath(), destinationFile)) { + if (!shellCopy(fileInfo.absoluteFilePath(), destinationFile)) { qCritical("failed to copy %s to %s", fileInfo.absoluteFilePath().toUtf8().constData(), destinationFile.toUtf8().constData()); From d417229e6bbaaf393d9172b3c46ee36d285f2196 Mon Sep 17 00:00:00 2001 From: TanninOne Date: Mon, 28 Dec 2015 13:54:16 +0100 Subject: [PATCH 8/8] executables installed as mods are now run through a proxy (not working yet) --- src/organizercore.cpp | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 6a8e148f..2caf0241 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -997,7 +997,31 @@ HANDLE OrganizerCore::spawnBinaryDirect(const QFileInfo &binary, const QString & // TODO: should also pass arguments if (m_AboutToRun(binary.absoluteFilePath())) { m_USVFS.updateMapping(fileMapping()); - return startBinary(binary, arguments, currentDirectory, true); + QString modsPath(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::modsPath())); + + QString binPath = binary.absoluteFilePath(); + + if (binPath.startsWith(modsPath, Qt::CaseInsensitive)) { + // binary was installed as a MO mod. Need to start it through a (hooked) + // proxy to ensure pathes are correct + + QString cwdPath = currentDirectory.absolutePath(); + + int binOffset = binPath.indexOf('/', modsPath.length() + 1); + int cwdOffset = cwdPath.indexOf('/', cwdPath.length() + 1); + QString binPath = m_GamePlugin->dataDirectory().absolutePath() + "/" + binPath.mid(binOffset); + QString cwd = m_GamePlugin->dataDirectory().absolutePath() + "/" + cwdPath.mid(cwdOffset); + QString cmdline = QString("launch \"%1\" \"%2\" %3") + .arg(QDir::toNativeSeparators(cwd), + QDir::toNativeSeparators(binPath), + arguments); + + return startBinary(QFileInfo(QCoreApplication::applicationDirPath() + "/helper.exe"), + cmdline, + QCoreApplication::applicationDirPath(), true); + } else { + return startBinary(binary, arguments, currentDirectory, true); + } } else { qDebug("start of \"%s\" canceled by plugin", qPrintable(binary.absoluteFilePath())); return INVALID_HANDLE_VALUE; @@ -1576,7 +1600,7 @@ std::vector OrganizerCore::fileMapping() int overwriteId = m_DirectoryStructure->getOriginByName(L"Overwrite").getID(); - IPluginGame *game = qApp->property("managed_game").value(); + const IPluginGame *game = qApp->property("managed_game").value(); MappingType result = fileMapping( QDir::toNativeSeparators(game->dataDirectory().absolutePath()), "\\", @@ -1585,11 +1609,12 @@ std::vector OrganizerCore::fileMapping() if (m_CurrentProfile->localSavesEnabled()) { LocalSavegames *localSaves = game->feature(); - if (localSaves != nullptr) { MappingType saveMap = localSaves->mappings(currentProfile()->absolutePath() + "/saves"); result.reserve(result.size() + saveMap.size()); result.insert(result.end(), saveMap.begin(), saveMap.end()); + } else { + qWarning("local save games not supported by this game plugin"); } }