diff options
author | Thomas Groman <tgroman@nuegia.net> | 2019-09-19 00:41:48 -0700 |
---|---|---|
committer | Thomas Groman <tgroman@nuegia.net> | 2019-09-19 00:41:48 -0700 |
commit | 32b3ed0a1362a4b0798ad71fac3450fb77cb7e41 (patch) | |
tree | 7be7a2f602e6a5af7bc2db86bef9cf2a659c3d3d /api/logic/minecraft/launch | |
parent | 5fb2c6334e7d5237db11695b4c0ec0f2d1e47c88 (diff) | |
download | MultiMC-32b3ed0a1362a4b0798ad71fac3450fb77cb7e41.tar MultiMC-32b3ed0a1362a4b0798ad71fac3450fb77cb7e41.tar.gz MultiMC-32b3ed0a1362a4b0798ad71fac3450fb77cb7e41.tar.lz MultiMC-32b3ed0a1362a4b0798ad71fac3450fb77cb7e41.tar.xz MultiMC-32b3ed0a1362a4b0798ad71fac3450fb77cb7e41.zip |
merged from 0.6.7 codebase
Diffstat (limited to 'api/logic/minecraft/launch')
18 files changed, 692 insertions, 498 deletions
diff --git a/api/logic/minecraft/launch/ClaimAccount.cpp b/api/logic/minecraft/launch/ClaimAccount.cpp index 71670b4f..a1180f0a 100644 --- a/api/logic/minecraft/launch/ClaimAccount.cpp +++ b/api/logic/minecraft/launch/ClaimAccount.cpp @@ -3,22 +3,22 @@ ClaimAccount::ClaimAccount(LaunchTask* parent, AuthSessionPtr session): LaunchStep(parent) { - if(session->status == AuthSession::Status::PlayableOnline) - { - m_account = session->m_accountPtr; - } + if(session->status == AuthSession::Status::PlayableOnline) + { + m_account = session->m_accountPtr; + } } void ClaimAccount::executeTask() { - if(m_account) - { - lock.reset(new UseLock(m_account)); - emitSucceeded(); - } + if(m_account) + { + lock.reset(new UseLock(m_account)); + emitSucceeded(); + } } void ClaimAccount::finalize() { - lock.reset(); + lock.reset(); } diff --git a/api/logic/minecraft/launch/ClaimAccount.h b/api/logic/minecraft/launch/ClaimAccount.h index de9007d1..d0892981 100644 --- a/api/logic/minecraft/launch/ClaimAccount.h +++ b/api/logic/minecraft/launch/ClaimAccount.h @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,16 +20,18 @@ class ClaimAccount: public LaunchStep { - Q_OBJECT + Q_OBJECT public: - explicit ClaimAccount(LaunchTask *parent, AuthSessionPtr session); - void executeTask() override; - void finalize() override; - bool canAbort() const override - { - return false; - } + explicit ClaimAccount(LaunchTask *parent, AuthSessionPtr session); + virtual ~ClaimAccount() {}; + + void executeTask() override; + void finalize() override; + bool canAbort() const override + { + return false; + } private: - std::unique_ptr<UseLock> lock; - MojangAccountPtr m_account; + std::unique_ptr<UseLock> lock; + MojangAccountPtr m_account; }; diff --git a/api/logic/minecraft/launch/CreateServerResourcePacksFolder.cpp b/api/logic/minecraft/launch/CreateServerResourcePacksFolder.cpp index 5398f7d0..ae426e31 100644 --- a/api/logic/minecraft/launch/CreateServerResourcePacksFolder.cpp +++ b/api/logic/minecraft/launch/CreateServerResourcePacksFolder.cpp @@ -9,11 +9,11 @@ CreateServerResourcePacksFolder::CreateServerResourcePacksFolder(LaunchTask* par void CreateServerResourcePacksFolder::executeTask() { - auto instance = m_parent->instance(); - std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance); - if(!FS::ensureFolderPathExists(FS::PathCombine(minecraftInstance->minecraftRoot(), "server-resource-packs"))) - { - emit logLine(tr("Couldn't create the 'server-resource-packs' folder"), MessageLevel::Error); - } - emitSucceeded(); + auto instance = m_parent->instance(); + std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance); + if(!FS::ensureFolderPathExists(FS::PathCombine(minecraftInstance->gameRoot(), "server-resource-packs"))) + { + emit logLine(tr("Couldn't create the 'server-resource-packs' folder"), MessageLevel::Error); + } + emitSucceeded(); } diff --git a/api/logic/minecraft/launch/CreateServerResourcePacksFolder.h b/api/logic/minecraft/launch/CreateServerResourcePacksFolder.h index 92026ecb..00ab2f2d 100644 --- a/api/logic/minecraft/launch/CreateServerResourcePacksFolder.h +++ b/api/logic/minecraft/launch/CreateServerResourcePacksFolder.h @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,14 +22,16 @@ // HACK: this is a workaround for MCL-3732 - 'server-resource-packs' folder is created. class CreateServerResourcePacksFolder: public LaunchStep { - Q_OBJECT + Q_OBJECT public: - explicit CreateServerResourcePacksFolder(LaunchTask *parent); - virtual void executeTask(); - virtual bool canAbort() const - { - return false; - } + explicit CreateServerResourcePacksFolder(LaunchTask *parent); + virtual ~CreateServerResourcePacksFolder() {}; + + virtual void executeTask(); + virtual bool canAbort() const + { + return false; + } }; diff --git a/api/logic/minecraft/launch/DirectJavaLaunch.cpp b/api/logic/minecraft/launch/DirectJavaLaunch.cpp index 4ccc5c3c..5c2bb91e 100644 --- a/api/logic/minecraft/launch/DirectJavaLaunch.cpp +++ b/api/logic/minecraft/launch/DirectJavaLaunch.cpp @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,128 +22,128 @@ DirectJavaLaunch::DirectJavaLaunch(LaunchTask *parent) : LaunchStep(parent) { - connect(&m_process, &LoggedProcess::log, this, &DirectJavaLaunch::logLines); - connect(&m_process, &LoggedProcess::stateChanged, this, &DirectJavaLaunch::on_state); + connect(&m_process, &LoggedProcess::log, this, &DirectJavaLaunch::logLines); + connect(&m_process, &LoggedProcess::stateChanged, this, &DirectJavaLaunch::on_state); } void DirectJavaLaunch::executeTask() { - auto instance = m_parent->instance(); - std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance); - QStringList args = minecraftInstance->javaArguments(); + auto instance = m_parent->instance(); + std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance); + QStringList args = minecraftInstance->javaArguments(); - args.append("-Djava.library.path=" + minecraftInstance->getNativePath()); + args.append("-Djava.library.path=" + minecraftInstance->getNativePath()); - auto classPathEntries = minecraftInstance->getClassPath(); - args.append("-cp"); - QString classpath; + auto classPathEntries = minecraftInstance->getClassPath(); + args.append("-cp"); + QString classpath; #ifdef Q_OS_WIN32 - classpath = classPathEntries.join(';'); + classpath = classPathEntries.join(';'); #else - classpath = classPathEntries.join(':'); + classpath = classPathEntries.join(':'); #endif - args.append(classpath); - args.append(minecraftInstance->getMainClass()); - - QString allArgs = args.join(", "); - emit logLine("Java Arguments:\n[" + m_parent->censorPrivateInfo(allArgs) + "]\n\n", MessageLevel::MultiMC); - - auto javaPath = FS::ResolveExecutable(instance->settings()->get("JavaPath").toString()); - - m_process.setProcessEnvironment(instance->createEnvironment()); - - // make detachable - this will keep the process running even if the object is destroyed - m_process.setDetachable(true); - - auto mcArgs = minecraftInstance->processMinecraftArgs(m_session); - args.append(mcArgs); - - QString wrapperCommandStr = instance->getWrapperCommand().trimmed(); - if(!wrapperCommandStr.isEmpty()) - { - auto wrapperArgs = Commandline::splitArgs(wrapperCommandStr); - auto wrapperCommand = wrapperArgs.takeFirst(); - auto realWrapperCommand = QStandardPaths::findExecutable(wrapperCommand); - if (realWrapperCommand.isEmpty()) - { - QString reason = tr("The wrapper command \"%1\" couldn't be found.").arg(wrapperCommand); - emit logLine(reason, MessageLevel::Fatal); - emitFailed(reason); - return; - } - emit logLine("Wrapper command is:\n" + wrapperCommandStr + "\n\n", MessageLevel::MultiMC); - args.prepend(javaPath); - m_process.start(wrapperCommand, wrapperArgs + args); - } - else - { - m_process.start(javaPath, args); - } + args.append(classpath); + args.append(minecraftInstance->getMainClass()); + + QString allArgs = args.join(", "); + emit logLine("Java Arguments:\n[" + m_parent->censorPrivateInfo(allArgs) + "]\n\n", MessageLevel::MultiMC); + + auto javaPath = FS::ResolveExecutable(instance->settings()->get("JavaPath").toString()); + + m_process.setProcessEnvironment(instance->createEnvironment()); + + // make detachable - this will keep the process running even if the object is destroyed + m_process.setDetachable(true); + + auto mcArgs = minecraftInstance->processMinecraftArgs(m_session); + args.append(mcArgs); + + QString wrapperCommandStr = instance->getWrapperCommand().trimmed(); + if(!wrapperCommandStr.isEmpty()) + { + auto wrapperArgs = Commandline::splitArgs(wrapperCommandStr); + auto wrapperCommand = wrapperArgs.takeFirst(); + auto realWrapperCommand = QStandardPaths::findExecutable(wrapperCommand); + if (realWrapperCommand.isEmpty()) + { + QString reason = tr("The wrapper command \"%1\" couldn't be found.").arg(wrapperCommand); + emit logLine(reason, MessageLevel::Fatal); + emitFailed(reason); + return; + } + emit logLine("Wrapper command is:\n" + wrapperCommandStr + "\n\n", MessageLevel::MultiMC); + args.prepend(javaPath); + m_process.start(wrapperCommand, wrapperArgs + args); + } + else + { + m_process.start(javaPath, args); + } } void DirectJavaLaunch::on_state(LoggedProcess::State state) { - switch(state) - { - case LoggedProcess::FailedToStart: - { - //: Error message displayed if instace can't start - QString reason = tr("Could not launch minecraft!"); - emit logLine(reason, MessageLevel::Fatal); - emitFailed(reason); - return; - } - case LoggedProcess::Aborted: - case LoggedProcess::Crashed: - - { - m_parent->setPid(-1); - emitFailed("Game crashed."); - return; - } - case LoggedProcess::Finished: - { - m_parent->setPid(-1); - // if the exit code wasn't 0, report this as a crash - auto exitCode = m_process.exitCode(); - if(exitCode != 0) - { - emitFailed("Game crashed."); - return; - } - //FIXME: make this work again - // m_postlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(exitCode)); - // run post-exit - emitSucceeded(); - break; - } - case LoggedProcess::Running: - emit logLine(tr("Minecraft process ID: %1\n\n").arg(m_process.processId()), MessageLevel::MultiMC); - m_parent->setPid(m_process.processId()); - m_parent->instance()->setLastLaunch(); - break; - default: - break; - } + switch(state) + { + case LoggedProcess::FailedToStart: + { + //: Error message displayed if instace can't start + QString reason = tr("Could not launch minecraft!"); + emit logLine(reason, MessageLevel::Fatal); + emitFailed(reason); + return; + } + case LoggedProcess::Aborted: + case LoggedProcess::Crashed: + + { + m_parent->setPid(-1); + emitFailed("Game crashed."); + return; + } + case LoggedProcess::Finished: + { + m_parent->setPid(-1); + // if the exit code wasn't 0, report this as a crash + auto exitCode = m_process.exitCode(); + if(exitCode != 0) + { + emitFailed("Game crashed."); + return; + } + //FIXME: make this work again + // m_postlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(exitCode)); + // run post-exit + emitSucceeded(); + break; + } + case LoggedProcess::Running: + emit logLine(tr("Minecraft process ID: %1\n\n").arg(m_process.processId()), MessageLevel::MultiMC); + m_parent->setPid(m_process.processId()); + m_parent->instance()->setLastLaunch(); + break; + default: + break; + } } void DirectJavaLaunch::setWorkingDirectory(const QString &wd) { - m_process.setWorkingDirectory(wd); + m_process.setWorkingDirectory(wd); } void DirectJavaLaunch::proceed() { - // nil + // nil } bool DirectJavaLaunch::abort() { - auto state = m_process.state(); - if (state == LoggedProcess::Running || state == LoggedProcess::Starting) - { - m_process.kill(); - } - return true; + auto state = m_process.state(); + if (state == LoggedProcess::Running || state == LoggedProcess::Starting) + { + m_process.kill(); + } + return true; } diff --git a/api/logic/minecraft/launch/DirectJavaLaunch.h b/api/logic/minecraft/launch/DirectJavaLaunch.h index 19087b50..9f57272c 100644 --- a/api/logic/minecraft/launch/DirectJavaLaunch.h +++ b/api/logic/minecraft/launch/DirectJavaLaunch.h @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,27 +21,29 @@ class DirectJavaLaunch: public LaunchStep { - Q_OBJECT + Q_OBJECT public: - explicit DirectJavaLaunch(LaunchTask *parent); - virtual void executeTask(); - virtual bool abort(); - virtual void proceed(); - virtual bool canAbort() const - { - return true; - } - void setWorkingDirectory(const QString &wd); - void setAuthSession(AuthSessionPtr session) - { - m_session = session; - } + explicit DirectJavaLaunch(LaunchTask *parent); + virtual ~DirectJavaLaunch() {}; + + virtual void executeTask(); + virtual bool abort(); + virtual void proceed(); + virtual bool canAbort() const + { + return true; + } + void setWorkingDirectory(const QString &wd); + void setAuthSession(AuthSessionPtr session) + { + m_session = session; + } private slots: - void on_state(LoggedProcess::State state); + void on_state(LoggedProcess::State state); private: - LoggedProcess m_process; - QString m_command; - AuthSessionPtr m_session; + LoggedProcess m_process; + QString m_command; + AuthSessionPtr m_session; }; diff --git a/api/logic/minecraft/launch/ExtractNatives.cpp b/api/logic/minecraft/launch/ExtractNatives.cpp index 7ddde374..253d13bc 100644 --- a/api/logic/minecraft/launch/ExtractNatives.cpp +++ b/api/logic/minecraft/launch/ExtractNatives.cpp @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,76 +25,76 @@ static QString replaceSuffix (QString target, const QString &suffix, const QString &replacement) { - if (!target.endsWith(suffix)) - { - return target; - } - target.resize(target.length() - suffix.length()); - return target + replacement; + if (!target.endsWith(suffix)) + { + return target; + } + target.resize(target.length() - suffix.length()); + return target + replacement; } static bool unzipNatives(QString source, QString targetFolder, bool applyJnilibHack) { - QuaZip zip(source); - if(!zip.open(QuaZip::mdUnzip)) - { - return false; - } - QDir directory(targetFolder); - if (!zip.goToFirstFile()) - { - return false; - } - do - { - QString name = zip.getCurrentFileName(); - if(applyJnilibHack) - { - name = replaceSuffix(name, ".jnilib", ".dylib"); - } - QString absFilePath = directory.absoluteFilePath(name); - if (!JlCompress::extractFile(&zip, "", absFilePath)) - { - return false; - } - } while (zip.goToNextFile()); - zip.close(); - if(zip.getZipError()!=0) - { - return false; - } - return true; + QuaZip zip(source); + if(!zip.open(QuaZip::mdUnzip)) + { + return false; + } + QDir directory(targetFolder); + if (!zip.goToFirstFile()) + { + return false; + } + do + { + QString name = zip.getCurrentFileName(); + if(applyJnilibHack) + { + name = replaceSuffix(name, ".jnilib", ".dylib"); + } + QString absFilePath = directory.absoluteFilePath(name); + if (!JlCompress::extractFile(&zip, "", absFilePath)) + { + return false; + } + } while (zip.goToNextFile()); + zip.close(); + if(zip.getZipError()!=0) + { + return false; + } + return true; } void ExtractNatives::executeTask() { - auto instance = m_parent->instance(); - std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance); - auto toExtract = minecraftInstance->getNativeJars(); - if(toExtract.isEmpty()) - { - emitSucceeded(); - return; - } - auto outputPath = minecraftInstance->getNativePath(); - auto javaVersion = minecraftInstance->getJavaVersion(); - bool jniHackEnabled = javaVersion.major() >= 8; - for(const auto &source: toExtract) - { - if(!unzipNatives(source, outputPath, jniHackEnabled)) - { - auto reason = tr("Couldn't extract native jar '%1' to destination '%2'").arg(source, outputPath); - emit logLine(reason, MessageLevel::Fatal); - emitFailed(reason); - } - } - emitSucceeded(); + auto instance = m_parent->instance(); + std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance); + auto toExtract = minecraftInstance->getNativeJars(); + if(toExtract.isEmpty()) + { + emitSucceeded(); + return; + } + auto outputPath = minecraftInstance->getNativePath(); + auto javaVersion = minecraftInstance->getJavaVersion(); + bool jniHackEnabled = javaVersion.major() >= 8; + for(const auto &source: toExtract) + { + if(!unzipNatives(source, outputPath, jniHackEnabled)) + { + auto reason = tr("Couldn't extract native jar '%1' to destination '%2'").arg(source, outputPath); + emit logLine(reason, MessageLevel::Fatal); + emitFailed(reason); + } + } + emitSucceeded(); } void ExtractNatives::finalize() { - auto instance = m_parent->instance(); - QString target_dir = FS::PathCombine(instance->instanceRoot(), "natives/"); - QDir dir(target_dir); - dir.removeRecursively(); + auto instance = m_parent->instance(); + QString target_dir = FS::PathCombine(instance->instanceRoot(), "natives/"); + QDir dir(target_dir); + dir.removeRecursively(); } diff --git a/api/logic/minecraft/launch/ExtractNatives.h b/api/logic/minecraft/launch/ExtractNatives.h index 6e1e7cd4..abb3bd7a 100644 --- a/api/logic/minecraft/launch/ExtractNatives.h +++ b/api/logic/minecraft/launch/ExtractNatives.h @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,17 +22,17 @@ // FIXME: temporary wrapper for existing task. class ExtractNatives: public LaunchStep { - Q_OBJECT + Q_OBJECT public: - explicit ExtractNatives(LaunchTask *parent) : LaunchStep(parent){}; - virtual ~ExtractNatives(){}; + explicit ExtractNatives(LaunchTask *parent) : LaunchStep(parent){}; + virtual ~ExtractNatives(){}; - void executeTask() override; - bool canAbort() const override - { - return false; - } - void finalize() override; + void executeTask() override; + bool canAbort() const override + { + return false; + } + void finalize() override; }; diff --git a/api/logic/minecraft/launch/LauncherPartLaunch.cpp b/api/logic/minecraft/launch/LauncherPartLaunch.cpp index 1fe9c323..e854a3a6 100644 --- a/api/logic/minecraft/launch/LauncherPartLaunch.cpp +++ b/api/logic/minecraft/launch/LauncherPartLaunch.cpp @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,8 +24,8 @@ LauncherPartLaunch::LauncherPartLaunch(LaunchTask *parent) : LaunchStep(parent) { - connect(&m_process, &LoggedProcess::log, this, &LauncherPartLaunch::logLines); - connect(&m_process, &LoggedProcess::stateChanged, this, &LauncherPartLaunch::on_state); + connect(&m_process, &LoggedProcess::log, this, &LauncherPartLaunch::logLines); + connect(&m_process, &LoggedProcess::stateChanged, this, &LauncherPartLaunch::on_state); } #ifdef Q_OS_WIN @@ -33,187 +33,187 @@ LauncherPartLaunch::LauncherPartLaunch(LaunchTask *parent) : LaunchStep(parent) #include <windows.h> QString shortPathName(const QString & file) { - auto input = file.toStdWString(); - std::wstring output; - long length = GetShortPathNameW(input.c_str(), NULL, 0); - // NOTE: this resizing might seem weird... - // when GetShortPathNameW fails, it returns length including null character - // when it succeeds, it returns length excluding null character - // See: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364989(v=vs.85).aspx - output.resize(length); - GetShortPathNameW(input.c_str(),(LPWSTR)output.c_str(),length); - output.resize(length-1); - QString ret = QString::fromStdWString(output); - return ret; + auto input = file.toStdWString(); + std::wstring output; + long length = GetShortPathNameW(input.c_str(), NULL, 0); + // NOTE: this resizing might seem weird... + // when GetShortPathNameW fails, it returns length including null character + // when it succeeds, it returns length excluding null character + // See: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364989(v=vs.85).aspx + output.resize(length); + GetShortPathNameW(input.c_str(),(LPWSTR)output.c_str(),length); + output.resize(length-1); + QString ret = QString::fromStdWString(output); + return ret; } #endif // if the string survives roundtrip through local 8bit encoding... bool fitsInLocal8bit(const QString & string) { - return string == QString::fromLocal8Bit(string.toLocal8Bit()); + return string == QString::fromLocal8Bit(string.toLocal8Bit()); } void LauncherPartLaunch::executeTask() { - auto instance = m_parent->instance(); - std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance); + auto instance = m_parent->instance(); + std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance); - m_launchScript = minecraftInstance->createLaunchScript(m_session); - QStringList args = minecraftInstance->javaArguments(); - QString allArgs = args.join(", "); - emit logLine("Java Arguments:\n[" + m_parent->censorPrivateInfo(allArgs) + "]\n\n", MessageLevel::MultiMC); + m_launchScript = minecraftInstance->createLaunchScript(m_session); + QStringList args = minecraftInstance->javaArguments(); + QString allArgs = args.join(", "); + emit logLine("Java Arguments:\n[" + m_parent->censorPrivateInfo(allArgs) + "]\n\n", MessageLevel::MultiMC); - auto javaPath = FS::ResolveExecutable(instance->settings()->get("JavaPath").toString()); + auto javaPath = FS::ResolveExecutable(instance->settings()->get("JavaPath").toString()); - m_process.setProcessEnvironment(instance->createEnvironment()); + m_process.setProcessEnvironment(instance->createEnvironment()); - // make detachable - this will keep the process running even if the object is destroyed - m_process.setDetachable(true); + // make detachable - this will keep the process running even if the object is destroyed + m_process.setDetachable(true); - auto classPath = minecraftInstance->getClassPath(); - classPath.prepend(FS::PathCombine(ENV.getJarsPath(), "NewLaunch.jar")); + auto classPath = minecraftInstance->getClassPath(); + classPath.prepend(FS::PathCombine(ENV.getJarsPath(), "NewLaunch.jar")); - auto natPath = minecraftInstance->getNativePath(); + auto natPath = minecraftInstance->getNativePath(); #ifdef Q_OS_WIN - if (!fitsInLocal8bit(natPath)) - { - args << "-Djava.library.path=" + shortPathName(natPath); - } - else - { - args << "-Djava.library.path=" + natPath; - } + if (!fitsInLocal8bit(natPath)) + { + args << "-Djava.library.path=" + shortPathName(natPath); + } + else + { + args << "-Djava.library.path=" + natPath; + } #else - args << "-Djava.library.path=" + natPath; + args << "-Djava.library.path=" + natPath; #endif - args << "-cp"; + args << "-cp"; #ifdef Q_OS_WIN - QStringList processed; - for(auto & item: classPath) - { - if (!fitsInLocal8bit(item)) - { - processed << shortPathName(item); - } - else - { - processed << item; - } - } - args << processed.join(';'); + QStringList processed; + for(auto & item: classPath) + { + if (!fitsInLocal8bit(item)) + { + processed << shortPathName(item); + } + else + { + processed << item; + } + } + args << processed.join(';'); #else - args << classPath.join(':'); + args << classPath.join(':'); #endif - args << "org.multimc.EntryPoint"; - - qDebug() << args.join(' '); - - QString wrapperCommandStr = instance->getWrapperCommand().trimmed(); - if(!wrapperCommandStr.isEmpty()) - { - auto wrapperArgs = Commandline::splitArgs(wrapperCommandStr); - auto wrapperCommand = wrapperArgs.takeFirst(); - auto realWrapperCommand = QStandardPaths::findExecutable(wrapperCommand); - if (realWrapperCommand.isEmpty()) - { - QString reason = tr("The wrapper command \"%1\" couldn't be found.").arg(wrapperCommand); - emit logLine(reason, MessageLevel::Fatal); - emitFailed(reason); - return; - } - emit logLine("Wrapper command is:\n" + wrapperCommandStr + "\n\n", MessageLevel::MultiMC); - args.prepend(javaPath); - m_process.start(wrapperCommand, wrapperArgs + args); - } - else - { - m_process.start(javaPath, args); - } + args << "org.multimc.EntryPoint"; + + qDebug() << args.join(' '); + + QString wrapperCommandStr = instance->getWrapperCommand().trimmed(); + if(!wrapperCommandStr.isEmpty()) + { + auto wrapperArgs = Commandline::splitArgs(wrapperCommandStr); + auto wrapperCommand = wrapperArgs.takeFirst(); + auto realWrapperCommand = QStandardPaths::findExecutable(wrapperCommand); + if (realWrapperCommand.isEmpty()) + { + QString reason = tr("The wrapper command \"%1\" couldn't be found.").arg(wrapperCommand); + emit logLine(reason, MessageLevel::Fatal); + emitFailed(reason); + return; + } + emit logLine("Wrapper command is:\n" + wrapperCommandStr + "\n\n", MessageLevel::MultiMC); + args.prepend(javaPath); + m_process.start(wrapperCommand, wrapperArgs + args); + } + else + { + m_process.start(javaPath, args); + } } void LauncherPartLaunch::on_state(LoggedProcess::State state) { - switch(state) - { - case LoggedProcess::FailedToStart: - { - //: Error message displayed if instace can't start - QString reason = tr("Could not launch minecraft!"); - emit logLine(reason, MessageLevel::Fatal); - emitFailed(reason); - return; - } - case LoggedProcess::Aborted: - case LoggedProcess::Crashed: - - { - m_parent->setPid(-1); - emitFailed("Game crashed."); - return; - } - case LoggedProcess::Finished: - { - m_parent->setPid(-1); - // if the exit code wasn't 0, report this as a crash - auto exitCode = m_process.exitCode(); - if(exitCode != 0) - { - emitFailed("Game crashed."); - return; - } - //FIXME: make this work again - // m_postlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(exitCode)); - // run post-exit - emitSucceeded(); - break; - } - case LoggedProcess::Running: - emit logLine(tr("Minecraft process ID: %1\n\n").arg(m_process.processId()), MessageLevel::MultiMC); - m_parent->setPid(m_process.processId()); - m_parent->instance()->setLastLaunch(); - // send the launch script to the launcher part - m_process.write(m_launchScript.toUtf8()); - - mayProceed = true; - emit readyForLaunch(); - break; - default: - break; - } + switch(state) + { + case LoggedProcess::FailedToStart: + { + //: Error message displayed if instace can't start + QString reason = tr("Could not launch minecraft!"); + emit logLine(reason, MessageLevel::Fatal); + emitFailed(reason); + return; + } + case LoggedProcess::Aborted: + case LoggedProcess::Crashed: + + { + m_parent->setPid(-1); + emitFailed("Game crashed."); + return; + } + case LoggedProcess::Finished: + { + m_parent->setPid(-1); + // if the exit code wasn't 0, report this as a crash + auto exitCode = m_process.exitCode(); + if(exitCode != 0) + { + emitFailed("Game crashed."); + return; + } + //FIXME: make this work again + // m_postlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(exitCode)); + // run post-exit + emitSucceeded(); + break; + } + case LoggedProcess::Running: + emit logLine(tr("Minecraft process ID: %1\n\n").arg(m_process.processId()), MessageLevel::MultiMC); + m_parent->setPid(m_process.processId()); + m_parent->instance()->setLastLaunch(); + // send the launch script to the launcher part + m_process.write(m_launchScript.toUtf8()); + + mayProceed = true; + emit readyForLaunch(); + break; + default: + break; + } } void LauncherPartLaunch::setWorkingDirectory(const QString &wd) { - m_process.setWorkingDirectory(wd); + m_process.setWorkingDirectory(wd); } void LauncherPartLaunch::proceed() { - if(mayProceed) - { - QString launchString("launch\n"); - m_process.write(launchString.toUtf8()); - mayProceed = false; - } + if(mayProceed) + { + QString launchString("launch\n"); + m_process.write(launchString.toUtf8()); + mayProceed = false; + } } bool LauncherPartLaunch::abort() { - if(mayProceed) - { - mayProceed = false; - QString launchString("abort\n"); - m_process.write(launchString.toUtf8()); - } - else - { - auto state = m_process.state(); - if (state == LoggedProcess::Running || state == LoggedProcess::Starting) - { - m_process.kill(); - } - } - return true; + if(mayProceed) + { + mayProceed = false; + QString launchString("abort\n"); + m_process.write(launchString.toUtf8()); + } + else + { + auto state = m_process.state(); + if (state == LoggedProcess::Running || state == LoggedProcess::Starting) + { + m_process.kill(); + } + } + return true; } diff --git a/api/logic/minecraft/launch/LauncherPartLaunch.h b/api/logic/minecraft/launch/LauncherPartLaunch.h index d384c2d1..1bc4a5f8 100644 --- a/api/logic/minecraft/launch/LauncherPartLaunch.h +++ b/api/logic/minecraft/launch/LauncherPartLaunch.h @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,29 +21,31 @@ class LauncherPartLaunch: public LaunchStep { - Q_OBJECT + Q_OBJECT public: - explicit LauncherPartLaunch(LaunchTask *parent); - virtual void executeTask(); - virtual bool abort(); - virtual void proceed(); - virtual bool canAbort() const - { - return true; - } - void setWorkingDirectory(const QString &wd); - void setAuthSession(AuthSessionPtr session) - { - m_session = session; - } + explicit LauncherPartLaunch(LaunchTask *parent); + virtual ~LauncherPartLaunch() {}; + + virtual void executeTask(); + virtual bool abort(); + virtual void proceed(); + virtual bool canAbort() const + { + return true; + } + void setWorkingDirectory(const QString &wd); + void setAuthSession(AuthSessionPtr session) + { + m_session = session; + } private slots: - void on_state(LoggedProcess::State state); + void on_state(LoggedProcess::State state); private: - LoggedProcess m_process; - QString m_command; - AuthSessionPtr m_session; - QString m_launchScript; - bool mayProceed = false; + LoggedProcess m_process; + QString m_command; + AuthSessionPtr m_session; + QString m_launchScript; + bool mayProceed = false; }; diff --git a/api/logic/minecraft/launch/ModMinecraftJar.cpp b/api/logic/minecraft/launch/ModMinecraftJar.cpp index 34825b45..ceaad175 100644 --- a/api/logic/minecraft/launch/ModMinecraftJar.cpp +++ b/api/logic/minecraft/launch/ModMinecraftJar.cpp @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,60 +23,60 @@ void ModMinecraftJar::executeTask() { - auto m_inst = std::dynamic_pointer_cast<MinecraftInstance>(m_parent->instance()); + auto m_inst = std::dynamic_pointer_cast<MinecraftInstance>(m_parent->instance()); - if(!m_inst->getJarMods().size()) - { - emitSucceeded(); - return; - } - // nuke obsolete stripped jar(s) if needed - if(!FS::ensureFolderPathExists(m_inst->binRoot())) - { - emitFailed(tr("Couldn't create the bin folder for Minecraft.jar")); - } + if(!m_inst->getJarMods().size()) + { + emitSucceeded(); + return; + } + // nuke obsolete stripped jar(s) if needed + if(!FS::ensureFolderPathExists(m_inst->binRoot())) + { + emitFailed(tr("Couldn't create the bin folder for Minecraft.jar")); + } - auto finalJarPath = QDir(m_inst->binRoot()).absoluteFilePath("minecraft.jar"); - if(!removeJar()) - { - emitFailed(tr("Couldn't remove stale jar file: %1").arg(finalJarPath)); - } + auto finalJarPath = QDir(m_inst->binRoot()).absoluteFilePath("minecraft.jar"); + if(!removeJar()) + { + emitFailed(tr("Couldn't remove stale jar file: %1").arg(finalJarPath)); + } - // create temporary modded jar, if needed - auto components = m_inst->getComponentList(); - auto profile = components->getProfile(); - auto jarMods = m_inst->getJarMods(); - if(jarMods.size()) - { - auto mainJar = profile->getMainJar(); - QStringList jars, temp1, temp2, temp3, temp4; - mainJar->getApplicableFiles(currentSystem, jars, temp1, temp2, temp3, m_inst->getLocalLibraryPath()); - auto sourceJarPath = jars[0]; - if(!MMCZip::createModdedJar(sourceJarPath, finalJarPath, jarMods)) - { - emitFailed(tr("Failed to create the custom Minecraft jar file.")); - return; - } - } - emitSucceeded(); + // create temporary modded jar, if needed + auto components = m_inst->getComponentList(); + auto profile = components->getProfile(); + auto jarMods = m_inst->getJarMods(); + if(jarMods.size()) + { + auto mainJar = profile->getMainJar(); + QStringList jars, temp1, temp2, temp3, temp4; + mainJar->getApplicableFiles(currentSystem, jars, temp1, temp2, temp3, m_inst->getLocalLibraryPath()); + auto sourceJarPath = jars[0]; + if(!MMCZip::createModdedJar(sourceJarPath, finalJarPath, jarMods)) + { + emitFailed(tr("Failed to create the custom Minecraft jar file.")); + return; + } + } + emitSucceeded(); } void ModMinecraftJar::finalize() { - removeJar(); + removeJar(); } bool ModMinecraftJar::removeJar() { - auto m_inst = std::dynamic_pointer_cast<MinecraftInstance>(m_parent->instance()); - auto finalJarPath = QDir(m_inst->binRoot()).absoluteFilePath("minecraft.jar"); - QFile finalJar(finalJarPath); - if(finalJar.exists()) - { - if(!finalJar.remove()) - { - return false; - } - } - return true; + auto m_inst = std::dynamic_pointer_cast<MinecraftInstance>(m_parent->instance()); + auto finalJarPath = QDir(m_inst->binRoot()).absoluteFilePath("minecraft.jar"); + QFile finalJar(finalJarPath); + if(finalJar.exists()) + { + if(!finalJar.remove()) + { + return false; + } + } + return true; } diff --git a/api/logic/minecraft/launch/ModMinecraftJar.h b/api/logic/minecraft/launch/ModMinecraftJar.h index b9a2d35b..bed5079f 100644 --- a/api/logic/minecraft/launch/ModMinecraftJar.h +++ b/api/logic/minecraft/launch/ModMinecraftJar.h @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,17 +20,17 @@ class ModMinecraftJar: public LaunchStep { - Q_OBJECT + Q_OBJECT public: - explicit ModMinecraftJar(LaunchTask *parent) : LaunchStep(parent) {}; - virtual ~ModMinecraftJar(){}; + explicit ModMinecraftJar(LaunchTask *parent) : LaunchStep(parent) {}; + virtual ~ModMinecraftJar(){}; - virtual void executeTask(); - virtual bool canAbort() const - { - return false; - } - void finalize() override; + virtual void executeTask() override; + virtual bool canAbort() const override + { + return false; + } + void finalize() override; private: - bool removeJar(); + bool removeJar(); }; diff --git a/api/logic/minecraft/launch/PrintInstanceInfo.cpp b/api/logic/minecraft/launch/PrintInstanceInfo.cpp index 83bf584f..4cc180fd 100644 --- a/api/logic/minecraft/launch/PrintInstanceInfo.cpp +++ b/api/logic/minecraft/launch/PrintInstanceInfo.cpp @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,67 +19,88 @@ #include "PrintInstanceInfo.h" #include <launch/LaunchTask.h> -void PrintInstanceInfo::executeTask() -{ - auto instance = m_parent->instance(); - auto lines = instance->verboseDescription(m_session); - #ifdef Q_OS_LINUX +namespace { +void probeProcCpuinfo(QStringList &log) +{ std::ifstream cpuin("/proc/cpuinfo"); for (std::string line; std::getline(cpuin, line);) { if (strncmp(line.c_str(), "model name", 10) == 0) { - QStringList clines = (QStringList() << QString::fromStdString(line.substr(13, std::string::npos))); - logLines(clines, MessageLevel::MultiMC); + log << QString::fromStdString(line.substr(13, std::string::npos)); break; } } +} +void runLspci(QStringList &log) +{ + // FIXME: fixed size buffers... char buff[512]; int gpuline = -1; int cline = 0; - FILE *fp = popen("lspci -k", "r"); - if (fp != NULL) + FILE * lspci = popen("lspci -k", "r"); + + if (!lspci) + return; + + while (fgets(buff, 512, lspci) != NULL) { - while (fgets(buff, 512, fp) != NULL) + std::string str(buff); + if (str.length() < 9) + continue; + if (str.substr(8, 3) == "VGA") { - std::string str(buff); - if (str.length() < 9) - continue; - if (str.substr(8, 3) == "VGA") - { - gpuline = cline; - QStringList glines = (QStringList() << QString::fromStdString(str.substr(35, std::string::npos))); - logLines(glines, MessageLevel::MultiMC); - } - if (gpuline > -1 && gpuline != cline) + gpuline = cline; + log << QString::fromStdString(str.substr(35, std::string::npos)); + } + if (gpuline > -1 && gpuline != cline) + { + if (cline - gpuline < 3) { - if (cline - gpuline < 3) - { - QStringList alines = (QStringList() << QString::fromStdString(str.substr(1, std::string::npos))); - logLines(alines, MessageLevel::MultiMC); - } + log << QString::fromStdString(str.substr(1, std::string::npos)); } - cline++; } + cline++; } - - FILE *fp2 = popen("glxinfo", "r"); - if (fp2 != NULL) + pclose(lspci); +} + +void runGlxinfo(QStringList & log) +{ + // FIXME: fixed size buffers... + char buff[512]; + FILE *glxinfo = popen("glxinfo", "r"); + if (!glxinfo) + return; + + while (fgets(buff, 512, glxinfo) != NULL) { - while (fgets(buff, 512, fp2) != NULL) + if (strncmp(buff, "OpenGL version string:", 22) == 0) { - if (strncmp(buff, "OpenGL version string:", 22) == 0) - { - QStringList drlines = (QStringList() << QString::fromUtf8(buff)); - logLines(drlines, MessageLevel::MultiMC); - break; - } + log << QString::fromUtf8(buff); + break; } } + pclose(glxinfo); +} + +} +#endif + +void PrintInstanceInfo::executeTask() +{ + auto instance = m_parent->instance(); + QStringList log; + +#ifdef Q_OS_LINUX + ::probeProcCpuinfo(log); + ::runLspci(log); + ::runGlxinfo(log); #endif - logLines(lines, MessageLevel::MultiMC); + logLines(log, MessageLevel::MultiMC); + logLines(instance->verboseDescription(m_session), MessageLevel::MultiMC); emitSucceeded(); } diff --git a/api/logic/minecraft/launch/PrintInstanceInfo.h b/api/logic/minecraft/launch/PrintInstanceInfo.h index 61615ba1..1d081f3e 100644 --- a/api/logic/minecraft/launch/PrintInstanceInfo.h +++ b/api/logic/minecraft/launch/PrintInstanceInfo.h @@ -1,4 +1,4 @@ -/* Copyright 2013-2018 MultiMC Contributors +/* Copyright 2013-2019 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,17 +22,17 @@ // FIXME: temporary wrapper for existing task. class PrintInstanceInfo: public LaunchStep { - Q_OBJECT + Q_OBJECT public: - explicit PrintInstanceInfo(LaunchTask *parent, AuthSessionPtr session) : LaunchStep(parent), m_session(session) {}; - virtual ~PrintInstanceInfo(){}; + explicit PrintInstanceInfo(LaunchTask *parent, AuthSessionPtr session) : LaunchStep(parent), m_session(session) {}; + virtual ~PrintInstanceInfo(){}; - virtual void executeTask(); - virtual bool canAbort() const - { - return false; - } + virtual void executeTask(); + virtual bool canAbort() const + { + return false; + } private: - AuthSessionPtr m_session; + AuthSessionPtr m_session; }; diff --git a/api/logic/minecraft/launch/ReconstructAssets.cpp b/api/logic/minecraft/launch/ReconstructAssets.cpp new file mode 100644 index 00000000..af9af127 --- /dev/null +++ b/api/logic/minecraft/launch/ReconstructAssets.cpp @@ -0,0 +1,36 @@ +/* Copyright 2013-2019 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ReconstructAssets.h" +#include "minecraft/MinecraftInstance.h" +#include "minecraft/ComponentList.h" +#include "minecraft/AssetsUtils.h" +#include "launch/LaunchTask.h" + +void ReconstructAssets::executeTask() +{ + auto instance = m_parent->instance(); + std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance); + auto components = minecraftInstance->getComponentList(); + auto profile = components->getProfile(); + auto assets = profile->getMinecraftAssets(); + + if(!AssetsUtils::reconstructAssets(assets->id, minecraftInstance->resourcesDir())) + { + emit logLine("Failed to reconstruct Minecraft assets.", MessageLevel::Error); + } + + emitSucceeded(); +} diff --git a/api/logic/minecraft/launch/ReconstructAssets.h b/api/logic/minecraft/launch/ReconstructAssets.h new file mode 100644 index 00000000..228fa083 --- /dev/null +++ b/api/logic/minecraft/launch/ReconstructAssets.h @@ -0,0 +1,33 @@ +/* Copyright 2013-2019 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <launch/LaunchStep.h> +#include <memory> + +class ReconstructAssets: public LaunchStep +{ + Q_OBJECT +public: + explicit ReconstructAssets(LaunchTask *parent) : LaunchStep(parent){}; + virtual ~ReconstructAssets(){}; + + void executeTask() override; + bool canAbort() const override + { + return false; + } +}; diff --git a/api/logic/minecraft/launch/ScanModFolders.cpp b/api/logic/minecraft/launch/ScanModFolders.cpp new file mode 100644 index 00000000..485c3dc4 --- /dev/null +++ b/api/logic/minecraft/launch/ScanModFolders.cpp @@ -0,0 +1,54 @@ +/* Copyright 2013-2019 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ScanModFolders.h" +#include "launch/LaunchTask.h" +#include "MMCZip.h" +#include "minecraft/OpSys.h" +#include "FileSystem.h" +#include "minecraft/MinecraftInstance.h" +#include "minecraft/mod/ModFolderModel.h" + +void ScanModFolders::executeTask() +{ + auto m_inst = std::dynamic_pointer_cast<MinecraftInstance>(m_parent->instance()); + + auto loaders = m_inst->loaderModList(); + connect(loaders.get(), &ModFolderModel::updateFinished, this, &ScanModFolders::modsDone); + loaders->update(); + + auto cores = m_inst->coreModList(); + connect(cores.get(), &ModFolderModel::updateFinished, this, &ScanModFolders::coreModsDone); + cores->update(); +} + +void ScanModFolders::modsDone() +{ + m_modsDone = true; + checkDone(); +} + +void ScanModFolders::coreModsDone() +{ + m_coreModsDone = true; + checkDone(); +} + +void ScanModFolders::checkDone() +{ + if(m_modsDone && m_coreModsDone) { + emitSucceeded(); + } +} diff --git a/api/logic/minecraft/launch/ScanModFolders.h b/api/logic/minecraft/launch/ScanModFolders.h new file mode 100644 index 00000000..360df98d --- /dev/null +++ b/api/logic/minecraft/launch/ScanModFolders.h @@ -0,0 +1,42 @@ +/* Copyright 2013-2019 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <launch/LaunchStep.h> +#include <memory> + +class ScanModFolders: public LaunchStep +{ + Q_OBJECT +public: + explicit ScanModFolders(LaunchTask *parent) : LaunchStep(parent) {}; + virtual ~ScanModFolders(){}; + + virtual void executeTask() override; + virtual bool canAbort() const override + { + return false; + } +private slots: + void coreModsDone(); + void modsDone(); +private: + void checkDone(); + +private: // DATA + bool m_modsDone = false; + bool m_coreModsDone = false; +}; |