diff options
Diffstat (limited to 'logic')
| -rw-r--r-- | logic/BaseInstance.cpp | 7 | ||||
| -rw-r--r-- | logic/BaseInstance.h | 2 | ||||
| -rw-r--r-- | logic/JavaChecker.cpp | 31 | ||||
| -rw-r--r-- | logic/JavaChecker.h | 4 | ||||
| -rw-r--r-- | logic/JavaCheckerJob.cpp | 6 | ||||
| -rw-r--r-- | logic/LegacyInstance.cpp | 59 | ||||
| -rw-r--r-- | logic/MinecraftProcess.cpp | 59 | ||||
| -rw-r--r-- | logic/MinecraftProcess.h | 15 | ||||
| -rw-r--r-- | logic/ModList.cpp | 2 | ||||
| -rw-r--r-- | logic/OneSixInstance.cpp | 88 | ||||
| -rw-r--r-- | logic/lists/JavaVersionList.cpp | 4 | ||||
| -rw-r--r-- | logic/net/CacheDownload.cpp | 100 | ||||
| -rw-r--r-- | logic/net/CacheDownload.h | 8 | ||||
| -rw-r--r-- | logic/net/URLConstants.h | 2 | ||||
| -rw-r--r-- | logic/status/StatusChecker.cpp | 137 | ||||
| -rw-r--r-- | logic/status/StatusChecker.h | 57 | ||||
| -rw-r--r-- | logic/updater/DownloadUpdateTask.cpp | 68 | ||||
| -rw-r--r-- | logic/updater/DownloadUpdateTask.h | 10 | ||||
| -rw-r--r-- | logic/updater/NotificationChecker.cpp | 121 | ||||
| -rw-r--r-- | logic/updater/NotificationChecker.h | 54 | ||||
| -rw-r--r-- | logic/updater/UpdateChecker.cpp | 12 | ||||
| -rw-r--r-- | logic/updater/UpdateChecker.h | 2 |
22 files changed, 616 insertions, 232 deletions
diff --git a/logic/BaseInstance.cpp b/logic/BaseInstance.cpp index ac66a8d5..4fc6b9dc 100644 --- a/logic/BaseInstance.cpp +++ b/logic/BaseInstance.cpp @@ -26,6 +26,7 @@ #include "overridesetting.h" #include "pathutils.h" +#include <cmdutils.h> #include "lists/MinecraftVersionList.h" #include "logic/icons/IconList.h" @@ -248,8 +249,14 @@ void BaseInstance::setName(QString val) d->m_settings->set("name", val); emit propertiesChanged(this); } + QString BaseInstance::name() const { I_D(BaseInstance); return d->m_settings->get("name").toString(); } + +QStringList BaseInstance::extraArguments() const +{ + return Util::Commandline::splitArgs(settings().get("JvmArgs").toString()); +} diff --git a/logic/BaseInstance.h b/logic/BaseInstance.h index 01d6dc7d..c059d058 100644 --- a/logic/BaseInstance.h +++ b/logic/BaseInstance.h @@ -81,6 +81,8 @@ public: void setGroupInitial(QString val); void setGroupPost(QString val); + QStringList extraArguments() const; + virtual QString intendedVersionId() const = 0; virtual bool setIntendedVersionId(QString version) = 0; diff --git a/logic/JavaChecker.cpp b/logic/JavaChecker.cpp index 113974ff..b87ee3d5 100644 --- a/logic/JavaChecker.cpp +++ b/logic/JavaChecker.cpp @@ -1,31 +1,28 @@ #include "JavaChecker.h" +#include "MultiMC.h" +#include <pathutils.h> #include <QFile> #include <QProcess> #include <QMap> #include <QTemporaryFile> -#define CHECKER_FILE "JavaChecker.jar" - JavaChecker::JavaChecker(QObject *parent) : QObject(parent) { } void JavaChecker::performCheck() { - checkerJar.setFileTemplate("checker_XXXXXX.jar"); - checkerJar.open(); - QFile inner(":/java/checker.jar"); - inner.open(QIODevice::ReadOnly); - checkerJar.write(inner.readAll()); - inner.close(); - checkerJar.close(); + QString checkerJar = PathCombine(MMC->bin(), "jars", "JavaCheck.jar"); - QStringList args = {"-jar", checkerJar.fileName()}; + QStringList args = {"-jar", checkerJar}; process.reset(new QProcess()); process->setArguments(args); process->setProgram(path); process->setProcessChannelMode(QProcess::SeparateChannels); + QLOG_DEBUG() << "Running java checker!"; + QLOG_DEBUG() << "Java: " + path; + QLOG_DEBUG() << "Args: {" + args.join("|") + "}"; connect(process.get(), SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(finished(int, QProcess::ExitStatus))); @@ -42,21 +39,25 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) killTimer.stop(); QProcessPtr _process; _process.swap(process); - checkerJar.remove(); JavaCheckResult result; { result.path = path; + result.id = id; } + QLOG_DEBUG() << "Java checker finished with status " << status << " exit code " << exitcode; if (status == QProcess::CrashExit || exitcode == 1) { + QLOG_DEBUG() << "Java checker failed!"; emit checkFinished(result); return; } bool success = true; QString p_stdout = _process->readAllStandardOutput(); + QLOG_DEBUG() << p_stdout; + QMap<QString, QString> results; QStringList lines = p_stdout.split("\n", QString::SkipEmptyParts); for(QString line : lines) @@ -76,6 +77,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) if(!results.contains("os.arch") || !results.contains("java.version") || !success) { + QLOG_DEBUG() << "Java checker failed - couldn't extract required information."; emit checkFinished(result); return; } @@ -90,7 +92,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) result.mojangPlatform = is_64 ? "64" : "32"; result.realPlatform = os_arch; result.javaVersion = java_version; - + QLOG_DEBUG() << "Java checker succeeded."; emit checkFinished(result); } @@ -99,11 +101,11 @@ void JavaChecker::error(QProcess::ProcessError err) if(err == QProcess::FailedToStart) { killTimer.stop(); - checkerJar.remove(); - + QLOG_DEBUG() << "Java checker has failed to start."; JavaCheckResult result; { result.path = path; + result.id = id; } emit checkFinished(result); @@ -116,6 +118,7 @@ void JavaChecker::timeout() // NO MERCY. NO ABUSE. if(process) { + QLOG_DEBUG() << "Java checker has been killed by timeout."; process->kill(); } } diff --git a/logic/JavaChecker.h b/logic/JavaChecker.h index 291bf46c..e19895f7 100644 --- a/logic/JavaChecker.h +++ b/logic/JavaChecker.h @@ -1,7 +1,6 @@ #pragma once #include <QProcess> #include <QTimer> -#include <QTemporaryFile> #include <memory> class JavaChecker; @@ -15,6 +14,7 @@ struct JavaCheckResult QString javaVersion; bool valid = false; bool is_64bit = false; + int id; }; typedef std::shared_ptr<QProcess> QProcessPtr; @@ -27,13 +27,13 @@ public: void performCheck(); QString path; + int id; signals: void checkFinished(JavaCheckResult result); private: QProcessPtr process; QTimer killTimer; - QTemporaryFile checkerJar; public slots: void timeout(); diff --git a/logic/JavaCheckerJob.cpp b/logic/JavaCheckerJob.cpp index 36a8a050..b0aea758 100644 --- a/logic/JavaCheckerJob.cpp +++ b/logic/JavaCheckerJob.cpp @@ -26,10 +26,7 @@ void JavaCheckerJob::partFinished(JavaCheckResult result) << javacheckers.size(); emit progress(num_finished, javacheckers.size()); - javaresults.append(result); - int result_size = javacheckers.size(); - - emit progress(num_finished, result_size); + javaresults.replace(result.id, result); if (num_finished == javacheckers.size()) { @@ -43,6 +40,7 @@ void JavaCheckerJob::start() m_running = true; for (auto iter : javacheckers) { + javaresults.append(JavaCheckResult()); connect(iter.get(), SIGNAL(checkFinished(JavaCheckResult)), SLOT(partFinished(JavaCheckResult))); iter->performCheck(); } diff --git a/logic/LegacyInstance.cpp b/logic/LegacyInstance.cpp index 0bc0961e..4b650e37 100644 --- a/logic/LegacyInstance.cpp +++ b/logic/LegacyInstance.cpp @@ -31,8 +31,6 @@ #include "gui/dialogs/LegacyModEditDialog.h" -#define LAUNCHER_FILE "MultiMCLauncher.jar" - LegacyInstance::LegacyInstance(const QString &rootDir, SettingsObject *settings, QObject *parent) : BaseInstance(new LegacyInstancePrivate(), rootDir, settings, parent) @@ -49,7 +47,7 @@ std::shared_ptr<Task> LegacyInstance::doUpdate(bool only_prepare) // make sure the jar mods list is initialized by asking for it. auto list = jarModList(); // create an update task - return std::shared_ptr<Task> (new LegacyUpdate(this, only_prepare , this)); + return std::shared_ptr<Task>(new LegacyUpdate(this, only_prepare, this)); } MinecraftProcess *LegacyInstance::prepareForLaunch(MojangAccountPtr account) @@ -60,58 +58,27 @@ MinecraftProcess *LegacyInstance::prepareForLaunch(MojangAccountPtr account) auto pixmap = icon.pixmap(128, 128); pixmap.save(PathCombine(minecraftRoot(), "icon.png"), "PNG"); - // extract the legacy launcher - QFile(":/java/launcher.jar").copy(PathCombine(minecraftRoot(), LAUNCHER_FILE)); - - // set the process arguments + // create the launch script + QString launchScript; { - QStringList args; - // window size - QString windowSize; + QString windowParams; if (settings().get("LaunchMaximized").toBool()) - windowSize = "max"; + windowParams = "max"; else - windowSize = QString("%1x%2").arg(settings().get("MinecraftWinWidth").toInt()).arg( + windowParams = QString("%1x%2").arg(settings().get("MinecraftWinWidth").toInt()).arg( settings().get("MinecraftWinHeight").toInt()); - // window title - QString windowTitle; - windowTitle.append("MultiMC: ").append(name()); - - // Java arguments - args.append(Util::Commandline::splitArgs(settings().get("JvmArgs").toString())); - -#ifdef OSX - // OSX dock icon and name - args << "-Xdock:icon=icon.png"; - args << QString("-Xdock:name=\"%1\"").arg(windowTitle); -#endif - QString lwjgl = QDir(MMC->settings()->get("LWJGLDir").toString() + "/" + lwjglVersion()) .absolutePath(); - - // launcher arguments - args << QString("-Xms%1m").arg(settings().get("MinMemAlloc").toInt()); - args << QString("-Xmx%1m").arg(settings().get("MaxMemAlloc").toInt()); - args << QString("-XX:PermSize=%1m").arg(settings().get("PermGen").toInt()); -/** -* HACK: Stupid hack for Intel drivers. -* See: https://mojang.atlassian.net/browse/MCL-767 -*/ -#ifdef Q_OS_WIN32 - args << QString("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_" - "minecraft.exe.heapdump"); -#endif - - args << "-jar" << LAUNCHER_FILE; - args << account->currentProfile()->name; - args << account->sessionId(); - args << windowTitle; - args << windowSize; - args << lwjgl; - proc->setArguments(args); + launchScript += "userName " + account->currentProfile()->name + "\n"; + launchScript += "sessionId " + account->sessionId() + "\n"; + launchScript += "windowTitle MultiMC: " + name() + "\n"; + launchScript += "windowParams " + windowParams + "\n"; + launchScript += "lwjgl " + lwjgl + "\n"; + launchScript += "launch legacy\n"; } + proc->setLaunchScript(launchScript); // set the process work path proc->setWorkdir(minecraftRoot()); diff --git a/logic/MinecraftProcess.cpp b/logic/MinecraftProcess.cpp index 209929b7..9c69f1a7 100644 --- a/logic/MinecraftProcess.cpp +++ b/logic/MinecraftProcess.cpp @@ -14,13 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "MultiMC.h" #include "MinecraftProcess.h" #include <QDataStream> #include <QFile> #include <QDir> -//#include <QImage> #include <QProcessEnvironment> #include "BaseInstance.h" @@ -59,11 +59,6 @@ MinecraftProcess::MinecraftProcess(BaseInstance *inst) : m_instance(inst) connect(this, SIGNAL(readyReadStandardOutput()), SLOT(on_stdOut())); } -void MinecraftProcess::setArguments(QStringList args) -{ - m_args = args; -} - void MinecraftProcess::setWorkdir(QString path) { QDir mcDir(path); @@ -90,6 +85,14 @@ QString MinecraftProcess::censorPrivateInfo(QString in) in.replace(profileId, "<PROFILE ID>"); in.replace(profileName, "<PROFILE NAME>"); } + + auto i = m_account->user().properties.begin(); + while (i != m_account->user().properties.end()) + { + in.replace(i.value(), "<" + i.key().toUpper() + ">"); + ++i; + } + return in; } @@ -189,13 +192,43 @@ void MinecraftProcess::launch() } m_instance->setLastLaunch(); + auto &settings = m_instance->settings(); + + //////////// java arguments //////////// + QStringList args; + { + // custom args go first. we want to override them if we have our own here. + args.append(m_instance->extraArguments()); + + // OSX dock icon and name + #ifdef OSX + args << "-Xdock:icon=icon.png"; + args << QString("-Xdock:name=\"%1\"").arg(windowTitle); + #endif + + // HACK: Stupid hack for Intel drivers. See: https://mojang.atlassian.net/browse/MCL-767 + #ifdef Q_OS_WIN32 + args << QString("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_" + "minecraft.exe.heapdump"); + #endif + + args << QString("-Xms%1m").arg(settings.get("MinMemAlloc").toInt()); + args << QString("-Xmx%1m").arg(settings.get("MaxMemAlloc").toInt()); + args << QString("-XX:PermSize=%1m").arg(settings.get("PermGen").toInt()); + if(!m_nativeFolder.isEmpty()) + args << QString("-Djava.library.path=%1").arg(m_nativeFolder); + args << "-jar" << PathCombine(MMC->bin(), "jars", "NewLaunch.jar"); + } - emit log(QString("Minecraft folder is: '%1'").arg(workingDirectory())); QString JavaPath = m_instance->settings().get("JavaPath").toString(); - emit log(QString("Java path: '%1'").arg(JavaPath)); - QString allArgs = m_args.join("' '"); - emit log(QString("Arguments: '%1'").arg(censorPrivateInfo(allArgs))); - start(JavaPath, m_args); + emit log("MultiMC version: " + MMC->version().toString() + "\n\n"); + emit log("Minecraft folder is:\n" + workingDirectory() + "\n\n"); + emit log("Java path is:\n" + JavaPath + "\n\n"); + QString allArgs = args.join(", "); + emit log("Java Arguments:\n[" + censorPrivateInfo(allArgs) + "]\n\n"); + + // instantiate the launcher part + start(JavaPath, args); if (!waitForStarted()) { //: Error message displayed if instace can't start @@ -204,11 +237,13 @@ void MinecraftProcess::launch() emit launch_failed(m_instance); return; } + // send the launch script to the launcher part + QByteArray bytes = launchScript.toUtf8(); + writeData(bytes.constData(), bytes.length()); } MessageLevel::Enum MinecraftProcess::getLevel(const QString &line, MessageLevel::Enum level) { - if (line.contains("[INFO]") || line.contains("[CONFIG]") || line.contains("[FINE]") || line.contains("[FINER]") || line.contains("[FINEST]")) level = MessageLevel::Message; diff --git a/logic/MinecraftProcess.h b/logic/MinecraftProcess.h index bd0151cc..5d1a2b71 100644 --- a/logic/MinecraftProcess.h +++ b/logic/MinecraftProcess.h @@ -18,7 +18,7 @@ #pragma once #include <QProcess> - +#include <QString> #include "BaseInstance.h" /** @@ -65,7 +65,15 @@ public: void setWorkdir(QString path); - void setArguments(QStringList args); + void setLaunchScript(QString script) + { + launchScript = script; + } + + void setNativeFolder(QString natives) + { + m_nativeFolder = natives; + } void killMinecraft(); @@ -104,12 +112,13 @@ signals: protected: BaseInstance *m_instance = nullptr; - QStringList m_args; QString m_err_leftover; QString m_out_leftover; QProcess m_prepostlaunchprocess; bool killed = false; MojangAccountPtr m_account; + QString launchScript; + QString m_nativeFolder; protected slots: diff --git a/logic/ModList.cpp b/logic/ModList.cpp index fd41bcf7..499623bf 100644 --- a/logic/ModList.cpp +++ b/logic/ModList.cpp @@ -416,7 +416,7 @@ QVariant ModList::data(const QModelIndex &index, int role) const switch (index.column()) { case ActiveColumn: - return mods[row].enabled(); + return mods[row].enabled() ? Qt::Checked: Qt::Unchecked; default: return QVariant(); } diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index 2392c683..a12cf047 100644 --- a/logic/OneSixInstance.cpp +++ b/logic/OneSixInstance.cpp @@ -13,12 +13,14 @@ * limitations under the License. */ +#include "MultiMC.h" #include "OneSixInstance.h" #include "OneSixInstance_p.h" #include "OneSixUpdate.h" #include "MinecraftProcess.h" #include "OneSixVersion.h" #include "JavaChecker.h" +#include "logic/icons/IconList.h" #include <setting.h> #include <pathutils.h> @@ -27,6 +29,7 @@ #include "gui/dialogs/OneSixModEditDialog.h" #include "logger/QsLog.h" #include "logic/assets/AssetsUtils.h" +#include <QIcon> OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *setting_obj, QObject *parent) @@ -40,7 +43,7 @@ OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *setting_o std::shared_ptr<Task> OneSixInstance::doUpdate(bool only_prepare) { - return std::shared_ptr<Task> (new OneSixUpdate(this, only_prepare)); + return std::shared_ptr<Task>(new OneSixUpdate(this, only_prepare)); } QString replaceTokensIn(QString text, QMap<QString, QString> with) @@ -78,24 +81,25 @@ QDir OneSixInstance::reconstructAssets(std::shared_ptr<OneSixVersion> version) QFile indexFile(indexPath); QDir virtualRoot(PathCombine(virtualDir.path(), version->assets)); - if(!indexFile.exists()) + if (!indexFile.exists()) { QLOG_ERROR() << "No assets index file" << indexPath << "; can't reconstruct assets"; return virtualRoot; } - QLOG_DEBUG() << "reconstructAssets" << assetsDir.path() << indexDir.path() << objectDir.path() << virtualDir.path() << virtualRoot.path(); + QLOG_DEBUG() << "reconstructAssets" << assetsDir.path() << indexDir.path() + << objectDir.path() << virtualDir.path() << virtualRoot.path(); AssetsIndex index; bool loadAssetsIndex = AssetsUtils::loadAssetsIndexJson(indexPath, &index); - if(loadAssetsIndex) + if (loadAssetsIndex) { - if(index.isVirtual) + if (index.isVirtual) { QLOG_INFO() << "Reconstructing virtual assets folder at" << virtualRoot.path(); - for(QString map : index.objects.keys()) + for (QString map : index.objects.keys()) { AssetObject asset_object = index.objects.value(map); QString target_path = PathCombine(virtualRoot.path(), map); @@ -103,17 +107,20 @@ QDir OneSixInstance::reconstructAssets(std::shared_ptr<OneSixVersion> version) QString tlk = asset_object.hash.left(2); - QString original_path = PathCombine(PathCombine(objectDir.path(), tlk), asset_object.hash); + QString original_path = + PathCombine(PathCombine(objectDir.path(), tlk), asset_object.hash); QFile original(original_path); - if(!target.exists()) + if (!target.exists()) { QFileInfo info(target_path); QDir target_dir = info.dir(); - //QLOG_DEBUG() << target_dir; - if(!target_dir.exists()) QDir("").mkpath(target_dir.path()); + // QLOG_DEBUG() << target_dir; + if (!target_dir.exists()) + QDir("").mkpath(target_dir.path()); bool couldCopy = original.copy(target_path); - QLOG_DEBUG() << " Copying" << original_path << "to" << target_path << QString::number(couldCopy);// << original.errorString(); + QLOG_DEBUG() << " Copying" << original_path << "to" << target_path + << QString::number(couldCopy); // << original.errorString(); } } @@ -155,7 +162,7 @@ QStringList OneSixInstance::processMinecraftArgs(MojangAccountPtr account) auto user = account->user(); QJsonObject userAttrs; - for(auto key: user.properties.keys()) + for (auto key : user.properties.keys()) { auto array = QJsonArray::fromStringList(user.properties.values(key)); userAttrs.insert(key, array); @@ -180,71 +187,56 @@ MinecraftProcess *OneSixInstance::prepareForLaunch(MojangAccountPtr account) { I_D(OneSixInstance); - QString natives_dir_raw = PathCombine(instanceRoot(), "natives/"); + QIcon icon = MMC->icons()->getIcon(iconKey()); + auto pixmap = icon.pixmap(128, 128); + pixmap.save(PathCombine(minecraftRoot(), "icon.png"), "PNG"); auto version = d->version; if (!version) return nullptr; - - QStringList args; - args.append(Util::Commandline::splitArgs(settings().get("JvmArgs").toString())); - args << QString("-Xms%1m").arg(settings().get("MinMemAlloc").toInt()); - args << QString("-Xmx%1m").arg(settings().get("MaxMemAlloc").toInt()); - args << QString("-XX:PermSize=%1m").arg(settings().get("PermGen").toInt()); - -/** - * HACK: Stupid hack for Intel drivers. - * See: https://mojang.atlassian.net/browse/MCL-767 - */ -#ifdef Q_OS_WIN32 - args << QString("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_" - "minecraft.exe.heapdump"); -#endif - - QDir natives_dir(natives_dir_raw); - args << QString("-Djava.library.path=%1").arg(natives_dir.absolutePath()); - QString classPath; + QString launchScript; { auto libs = version->getActiveNormalLibs(); for (auto lib : libs) { QFileInfo fi(QString("libraries/") + lib->storagePath()); - classPath.append(fi.absoluteFilePath()); -#ifdef Q_OS_WIN32 - classPath.append(';'); -#else - classPath.append(':'); -#endif + launchScript += "cp " + fi.absoluteFilePath() + "\n"; } QString targetstr = "versions/" + version->id + "/" + version->id + ".jar"; QFileInfo fi(targetstr); - classPath.append(fi.absoluteFilePath()); + launchScript += "cp " + fi.absoluteFilePath() + "\n"; } - if (classPath.size()) + launchScript += "mainClass " + version->mainClass + "\n"; + + for (auto param : processMinecraftArgs(account)) { - args << "-cp"; - args << classPath; + launchScript += "param " + param + "\n"; } - args << version->mainClass; - args.append(processMinecraftArgs(account)); // Set the width and height for 1.6 instances bool maximize = settings().get("LaunchMaximized").toBool(); if (maximize) { // this is probably a BAD idea - // args << QString("--fullscreen"); + // launchScript += "param --fullscreen\n"; } else { - args << QString("--width") << settings().get("MinecraftWinWidth").toString(); - args << QString("--height") << settings().get("MinecraftWinHeight").toString(); + launchScript += + "param --width\nparam " + settings().get("MinecraftWinWidth").toString() + "\n"; + launchScript += + "param --height\nparam " + settings().get("MinecraftWinHeight").toString() + "\n"; } + QDir natives_dir(PathCombine(instanceRoot(), "natives/")); + launchScript += "windowTitle MultiMC: " + name() + "\n"; + launchScript += "natives " + natives_dir.absolutePath() + "\n"; + launchScript += "launch onesix\n"; // create the process and set its parameters MinecraftProcess *proc = new MinecraftProcess(this); - proc->setArguments(args); proc->setWorkdir(minecraftRoot()); + proc->setLaunchScript(launchScript); + // proc->setNativeFolder(natives_dir.absolutePath()); return proc; } diff --git a/logic/lists/JavaVersionList.cpp b/logic/lists/JavaVersionList.cpp index e8c5acd0..eb1c5650 100644 --- a/logic/lists/JavaVersionList.cpp +++ b/logic/lists/JavaVersionList.cpp @@ -182,13 +182,17 @@ void JavaListLoadTask::executeTask() connect(m_job.get(), SIGNAL(progress(int, int)), this, SLOT(checkerProgress(int, int))); QLOG_DEBUG() << "Probing the following Java paths: "; + int id = 0; for(QString candidate : candidate_paths) { QLOG_DEBUG() << " " << candidate; auto candidate_checker = new JavaChecker(); candidate_checker->path = candidate; + candidate_checker->id = id; m_job->addJavaCheckerAction(JavaCheckerPtr(candidate_checker)); + + id++; } m_job->start(); diff --git a/logic/net/CacheDownload.cpp b/logic/net/CacheDownload.cpp index 6eadae39..8a8d00f0 100644 --- a/logic/net/CacheDownload.cpp +++ b/logic/net/CacheDownload.cpp @@ -33,8 +33,10 @@ CacheDownload::CacheDownload(QUrl url, MetaEntryPtr entry) void CacheDownload::start() { + m_status = Job_InProgress; if (!m_entry->stale) { + m_status = Job_Finished; emit succeeded(m_index_within_job); return; } @@ -42,6 +44,15 @@ void CacheDownload::start() // if there already is a file and md5 checking is in effect and it can be opened if (!ensureFilePathExists(m_target_path)) { + QLOG_ERROR() << "Could not create folder for " + m_target_path; + m_status = Job_Failed; + emit failed(m_index_within_job); + return; + } + if (!m_output_file.open(QIODevice::WriteOnly)) + { + QLOG_ERROR() << "Could not open " + m_target_path + " for writing"; + m_status = Job_Failed; emit failed(m_index_within_job); return; } @@ -83,70 +94,65 @@ void CacheDownload::downloadError(QNetworkReply::NetworkError error) void CacheDownload::downloadFinished() { // if the download succeeded - if (m_status != Job_Failed) + if (m_status == Job_Failed) { + m_output_file.cancelWriting(); + m_reply.reset(); + m_status = Job_Failed; + emit failed(m_index_within_job); + return; + } + if (wroteAnyData) + { // nothing went wrong... - m_status = Job_Finished; - if (m_output_file.isOpen()) + if (m_output_file.commit()) { - // save the data to the downloadable if we aren't saving to file - m_output_file.close(); + m_status = Job_Finished; m_entry->md5sum = md5sum.result().toHex().constData(); } else { - if (m_output_file.open(QIODevice::ReadOnly)) - { - m_entry->md5sum = - QCryptographicHash::hash(m_output_file.readAll(), QCryptographicHash::Md5) - .toHex() - .constData(); - m_output_file.close(); - } - } - QFileInfo output_file_info(m_target_path); - - m_entry->etag = m_reply->rawHeader("ETag").constData(); - if (m_reply->hasRawHeader("Last-Modified")) - { - m_entry->remote_changed_timestamp = m_reply->rawHeader("Last-Modified").constData(); + QLOG_ERROR() << "Failed to commit changes to " << m_target_path; + m_output_file.cancelWriting(); + m_reply.reset(); + m_status = Job_Failed; + emit failed(m_index_within_job); + return; } - m_entry->local_changed_timestamp = - output_file_info.lastModified().toUTC().toMSecsSinceEpoch(); - m_entry->stale = false; - MMC->metacache()->updateEntry(m_entry); - - m_reply.reset(); - emit succeeded(m_index_within_job); - return; } - // else the download failed else { - m_output_file.close(); - m_output_file.remove(); - m_reply.reset(); - emit failed(m_index_within_job); - return; + m_status = Job_Finished; } + + QFileInfo output_file_info(m_target_path); + + m_entry->etag = m_reply->rawHeader("ETag").constData(); + if (m_reply->hasRawHeader("Last-Modified")) + { + m_entry->remote_changed_timestamp = m_reply->rawHeader("Last-Modified").constData(); + } + m_entry->local_changed_timestamp = + output_file_info.lastModified().toUTC().toMSecsSinceEpoch(); + m_entry->stale = false; + MMC->metacache()->updateEntry(m_entry); + + m_reply.reset(); + emit succeeded(m_index_within_job); + return; } void CacheDownload::downloadReadyRead() { - if (!m_output_file.isOpen()) - { - if (!m_output_file.open(QIODevice::WriteOnly)) - { - /* - * Can't open the file... the job failed - */ - m_reply->abort(); - emit failed(m_index_within_job); - return; - } - } QByteArray ba = m_reply->readAll(); md5sum.addData(ba); - m_output_file.write(ba); + if (m_output_file.write(ba) != ba.size()) + { + QLOG_ERROR() << "Failed writing into " + m_target_path; + m_status = Job_Failed; + m_reply->abort(); + emit failed(m_index_within_job); + } + wroteAnyData = true; } diff --git a/logic/net/CacheDownload.h b/logic/net/CacheDownload.h index e25aecd2..48be1dae 100644 --- a/logic/net/CacheDownload.h +++ b/logic/net/CacheDownload.h @@ -17,8 +17,8 @@ #include "NetAction.h" #include "HttpMetaCache.h" -#include <QFile> -#include <qcryptographichash.h> +#include <QCryptographicHash> +#include <QSaveFile> typedef std::shared_ptr<class CacheDownload> CacheDownloadPtr; class CacheDownload : public NetAction @@ -29,10 +29,12 @@ public: /// if saving to file, use the one specified in this string QString m_target_path; /// this is the output file, if any - QFile m_output_file; + QSaveFile m_output_file; /// the hash-as-you-download QCryptographicHash md5sum; + bool wroteAnyData = false; + public: explicit CacheDownload(QUrl url, MetaEntryPtr entry); static CacheDownloadPtr make(QUrl url, MetaEntryPtr entry) diff --git a/logic/net/URLConstants.h b/logic/net/URLConstants.h index 9579198d..8cb1f3fd 100644 --- a/logic/net/URLConstants.h +++ b/logic/net/URLConstants.h @@ -31,4 +31,6 @@ const QString SKINS_BASE("skins.minecraft.net/MinecraftSkins/"); const QString AUTH_BASE("authserver.mojang.com/"); const QString FORGE_LEGACY_URL("http://files.minecraftforge.net/minecraftforge/json"); const QString FORGE_GRADLE_URL("http://files.minecraftforge.net/maven/net/minecraftforge/forge/json"); +const QString MOJANG_STATUS_URL("http://status.mojang.com/check"); +const QString MOJANG_STATUS_NEWS_URL("http://status.mojang.com/news"); } diff --git a/logic/status/StatusChecker.cpp b/logic/status/StatusChecker.cpp new file mode 100644 index 00000000..7c856d3f --- /dev/null +++ b/logic/status/StatusChecker.cpp @@ -0,0 +1,137 @@ +/* Copyright 2013 MultiMC Contributors |
