summaryrefslogtreecommitdiffstats
path: root/logic
diff options
context:
space:
mode:
authorPetr Mrázek <peterix@gmail.com>2014-01-20 01:32:38 +0100
committerPetr Mrázek <peterix@gmail.com>2014-01-20 01:32:38 +0100
commit222d3c0dc5a8b8a9e93b9368e964cda7becc7f02 (patch)
tree9ab4538f2e80847874a7c9a5c7c2dbc099cb8cae /logic
parent48b587e7b6b96b5c3ac17dc8b67a7b0ab9c2c4f0 (diff)
parent3a3c9ac9515447941d383f2c4fe4b0225fdd8252 (diff)
downloadMultiMC-222d3c0dc5a8b8a9e93b9368e964cda7becc7f02.tar
MultiMC-222d3c0dc5a8b8a9e93b9368e964cda7becc7f02.tar.gz
MultiMC-222d3c0dc5a8b8a9e93b9368e964cda7becc7f02.tar.lz
MultiMC-222d3c0dc5a8b8a9e93b9368e964cda7becc7f02.tar.xz
MultiMC-222d3c0dc5a8b8a9e93b9368e964cda7becc7f02.zip
Merge branch 'release-0.2'0.2
Diffstat (limited to 'logic')
-rw-r--r--logic/BaseInstance.cpp13
-rw-r--r--logic/BaseInstance.h7
-rw-r--r--logic/BaseVersion.h9
-rw-r--r--logic/JavaChecker.cpp13
-rw-r--r--logic/LegacyFTBInstance.cpp5
-rw-r--r--logic/LegacyFTBInstance.h1
-rw-r--r--logic/LegacyInstance.cpp57
-rw-r--r--logic/MinecraftProcess.cpp256
-rw-r--r--logic/MinecraftProcess.h32
-rw-r--r--logic/NagUtils.cpp18
-rw-r--r--logic/OneSixFTBInstance.cpp5
-rw-r--r--logic/OneSixFTBInstance.h2
-rw-r--r--logic/OneSixInstance.cpp121
-rw-r--r--logic/OneSixLibrary.cpp87
-rw-r--r--logic/OneSixLibrary.h3
-rw-r--r--logic/OneSixUpdate.cpp151
-rw-r--r--logic/OneSixUpdate.h8
-rw-r--r--logic/SkinUtils.h2
-rw-r--r--logic/auth/MojangAccount.cpp6
-rw-r--r--logic/icons/IconList.cpp17
-rw-r--r--logic/icons/IconList.h1
-rw-r--r--logic/lists/ForgeVersionList.cpp12
-rw-r--r--logic/lists/ForgeVersionList.h21
-rw-r--r--logic/lists/InstanceList.cpp73
-rw-r--r--logic/net/CacheDownload.cpp125
-rw-r--r--logic/net/CacheDownload.h15
-rw-r--r--logic/net/URLConstants.h2
-rw-r--r--logic/status/StatusChecker.cpp137
-rw-r--r--logic/status/StatusChecker.h57
-rw-r--r--logic/updater/NotificationChecker.cpp2
-rw-r--r--logic/updater/UpdateChecker.cpp1
-rw-r--r--logic/updater/UpdateChecker.h2
32 files changed, 868 insertions, 393 deletions
diff --git a/logic/BaseInstance.cpp b/logic/BaseInstance.cpp
index ac66a8d5..222004a3 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"
@@ -81,6 +82,7 @@ BaseInstance::BaseInstance(BaseInstancePrivate *d_in, const QString &rootDir,
settings().registerSetting("OverrideConsole", false);
settings().registerOverride(globalSettings->getSetting("ShowConsole"));
settings().registerOverride(globalSettings->getSetting("AutoCloseConsole"));
+ settings().registerOverride(globalSettings->getSetting("LogPrePostOutput"));
}
void BaseInstance::iconUpdated(QString key)
@@ -248,8 +250,19 @@ 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();
}
+
+QString BaseInstance::windowTitle() const
+{
+ return "MultiMC: " + name();
+}
+
+QStringList BaseInstance::extraArguments() const
+{
+ return Util::Commandline::splitArgs(settings().get("JvmArgs").toString());
+}
diff --git a/logic/BaseInstance.h b/logic/BaseInstance.h
index 01d6dc7d..a861e9b2 100644
--- a/logic/BaseInstance.h
+++ b/logic/BaseInstance.h
@@ -57,7 +57,7 @@ public:
/// The instance's ID. The ID SHALL be determined by MMC internally. The ID IS guaranteed to
/// be unique.
- QString id() const;
+ virtual QString id() const;
/// get the type of this instance
QString instanceType() const;
@@ -71,6 +71,9 @@ public:
QString name() const;
void setName(QString val);
+ /// Value used for instance window titles
+ QString windowTitle() const;
+
QString iconKey() const;
void setIconKey(QString val);
@@ -81,6 +84,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/BaseVersion.h b/logic/BaseVersion.h
index 1864c94c..43f5942a 100644
--- a/logic/BaseVersion.h
+++ b/logic/BaseVersion.h
@@ -39,6 +39,15 @@ struct BaseVersion
* the kind of version this is (Stable, Beta, Snapshot, whatever)
*/
virtual QString typeString() const = 0;
+
+ virtual bool operator<(BaseVersion &a)
+ {
+ return name() < a.name();
+ };
+ virtual bool operator>(BaseVersion &a)
+ {
+ return name() > a.name();
+ };
};
typedef std::shared_ptr<BaseVersion> BaseVersionPtr;
diff --git a/logic/JavaChecker.cpp b/logic/JavaChecker.cpp
index 6ee7b4cf..b87ee3d5 100644
--- a/logic/JavaChecker.cpp
+++ b/logic/JavaChecker.cpp
@@ -20,6 +20,9 @@ void JavaChecker::performCheck()
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,15 +45,19 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
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)
@@ -70,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;
}
@@ -84,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);
}
@@ -93,7 +101,7 @@ void JavaChecker::error(QProcess::ProcessError err)
if(err == QProcess::FailedToStart)
{
killTimer.stop();
-
+ QLOG_DEBUG() << "Java checker has failed to start.";
JavaCheckResult result;
{
result.path = path;
@@ -110,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/LegacyFTBInstance.cpp b/logic/LegacyFTBInstance.cpp
index 84d5a900..6c6bd10b 100644
--- a/logic/LegacyFTBInstance.cpp
+++ b/logic/LegacyFTBInstance.cpp
@@ -14,3 +14,8 @@ bool LegacyFTBInstance::menuActionEnabled(QString action_name) const
{
return false;
}
+
+QString LegacyFTBInstance::id() const
+{
+ return "FTB/" + BaseInstance::id();
+}
diff --git a/logic/LegacyFTBInstance.h b/logic/LegacyFTBInstance.h
index 2ae72797..70f60535 100644
--- a/logic/LegacyFTBInstance.h
+++ b/logic/LegacyFTBInstance.h
@@ -10,4 +10,5 @@ public:
QObject *parent = 0);
virtual QString getStatusbarDescription();
virtual bool menuActionEnabled(QString action_name) const;
+ virtual QString id() const;
};
diff --git a/logic/LegacyInstance.cpp b/logic/LegacyInstance.cpp
index 5ab19fc9..2828bcbf 100644
--- a/logic/LegacyInstance.cpp
+++ b/logic/LegacyInstance.cpp
@@ -47,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)
@@ -58,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
- QString launcherJar = PathCombine(MMC->bin(), "jars", "MultiMCLauncher.jar");
-
- // 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" << launcherJar;
- 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 " + windowTitle() + "\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..84610021 100644
--- a/logic/MinecraftProcess.cpp
+++ b/logic/MinecraftProcess.cpp
@@ -14,14 +14,15 @@
* 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 <QRegularExpression>
#include "BaseInstance.h"
@@ -42,6 +43,7 @@ MinecraftProcess::MinecraftProcess(BaseInstance *inst) : m_instance(inst)
#ifdef LINUX
// Strip IBus
+ // IBus is a Linux IME framework. For some reason, it breaks MC?
if (env.value("XMODIFIERS").contains(IBUS))
env.insert("XMODIFIERS", env.value("XMODIFIERS").replace(IBUS, ""));
#endif
@@ -57,11 +59,15 @@ MinecraftProcess::MinecraftProcess(BaseInstance *inst) : m_instance(inst)
// std channels
connect(this, SIGNAL(readyReadStandardError()), SLOT(on_stdErr()));
connect(this, SIGNAL(readyReadStandardOutput()), SLOT(on_stdOut()));
-}
-void MinecraftProcess::setArguments(QStringList args)
-{
- m_args = args;
+ // Log prepost launch command output (can be disabled.)
+ if (m_instance->settings().get("LogPrePostOutput").toBool())
+ {
+ connect(&m_prepostlaunchprocess, &QProcess::readyReadStandardError,
+ this, &MinecraftProcess::on_prepost_stdErr);
+ connect(&m_prepostlaunchprocess, &QProcess::readyReadStandardOutput,
+ this, &MinecraftProcess::on_prepost_stdOut);
+ }
}
void MinecraftProcess::setWorkdir(QString path)
@@ -90,47 +96,145 @@ 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;
}
// console window
+MessageLevel::Enum MinecraftProcess::guessLevel(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;
+ if (line.contains("[SEVERE]") || line.contains("[STDERR]"))
+ level = MessageLevel::Error;
+ if (line.contains("[WARNING]"))
+ level = MessageLevel::Warning;
+ if (line.contains("Exception in thread") || line.contains(" at "))
+ level = MessageLevel::Fatal;
+ if (line.contains("[DEBUG]"))
+ level = MessageLevel::Debug;
+ return level;
+}
+
+MessageLevel::Enum MinecraftProcess::getLevel(const QString &levelName)
+{
+ if (levelName == "MultiMC")
+ return MessageLevel::MultiMC;
+ else if (levelName == "Debug")
+ return MessageLevel::Debug;
+ else if (levelName == "Info")
+ return MessageLevel::Info;
+ else if (levelName == "Message")
+ return MessageLevel::Message;
+ else if (levelName == "Warning")
+ return MessageLevel::Warning;
+ else if (levelName == "Error")
+ return MessageLevel::Error;
+ else if (levelName == "Fatal")
+ return MessageLevel::Fatal;
+ // Skip PrePost, it's not exposed to !![]!
+ else
+ return MessageLevel::Message;
+}
+
+void MinecraftProcess::logOutput(const QStringList &lines,
+ MessageLevel::Enum defaultLevel,
+ bool guessLevel, bool censor)
+{
+ for (int i = 0; i < lines.size(); ++i)
+ logOutput(lines[i], defaultLevel, guessLevel, censor);
+}
+
+void MinecraftProcess::logOutput(QString line,
+ MessageLevel::Enum defaultLevel,
+ bool guessLevel, bool censor)
+{
+ MessageLevel::Enum level = defaultLevel;
+
+ // Level prefix
+ int endmark = line.indexOf("]!");
+ if (line.startsWith("!![") && endmark != -1)
+ {
+ level = getLevel(line.left(endmark).mid(3));
+ line = line.mid(endmark + 2);
+ }
+ // Guess level
+ else if (guessLevel)
+ level = this->guessLevel(line, defaultLevel);
+
+ if (censor)
+ line = censorPrivateInfo(line);
+
+ emit log(line, level);
+}
+
void MinecraftProcess::on_stdErr()
{
QByteArray data = readAllStandardError();
QString str = m_err_leftover + QString::fromLocal8Bit(data);
- m_err_leftover.clear();
+
QStringList lines = str.split("\n");
- bool complete = str.endsWith("\n");
+ m_err_leftover = lines.takeLast();
- for (int i = 0; i < lines.size() - 1; i++)
- {
- QString &line = lines[i];
- emit log(censorPrivateInfo(line), getLevel(line, MessageLevel::Error));
- }
- if (!complete)
- m_err_leftover = lines.last();
+ logOutput(lines, MessageLevel::Error);
}
void MinecraftProcess::on_stdOut()
{
QByteArray data = readAllStandardOutput();
QString str = m_out_leftover + QString::fromLocal8Bit(data);
- m_out_leftover.clear();
+
QStringList lines = str.split("\n");
- bool complete = str.endsWith("\n");
+ m_out_leftover = lines.takeLast();
- for (int i = 0; i < lines.size() - 1; i++)
- {
- QString &line = lines[i];
- emit log(censorPrivateInfo(line), getLevel(line, MessageLevel::Message));
- }
- if (!complete)
- m_out_leftover = lines.last();
+ logOutput(lines);
+}
+
+void MinecraftProcess::on_prepost_stdErr()
+{
+ QByteArray data = m_prepostlaunchprocess.readAllStandardError();
+ QString str = m_err_leftover + QString::fromLocal8Bit(data);
+
+ QStringList lines = str.split("\n");
+ m_err_leftover = lines.takeLast();
+
+ logOutput(lines, MessageLevel::PrePost, false, false);
+}
+
+void MinecraftProcess::on_prepost_stdOut()
+{
+ QByteArray data = m_prepostlaunchprocess.readAllStandardOutput();
+ QString str = m_out_leftover + QString::fromLocal8Bit(data);
+
+ QStringList lines = str.split("\n");
+ m_out_leftover = lines.takeLast();
+
+ logOutput(lines, MessageLevel::PrePost, false, false);
}
// exit handler
void MinecraftProcess::finish(int code, ExitStatus status)
{
+ // Flush console window
+ if (!m_err_leftover.isEmpty())
+ {
+ logOutput(m_err_leftover, MessageLevel::Error);
+ m_err_leftover.clear();
+ }
+ if (!m_out_leftover.isEmpty())
+ {
+ logOutput(m_out_leftover);
+ m_out_leftover.clear();
+ }
+
if (!killed)
{
if (status == NormalExit)
@@ -153,15 +257,32 @@ void MinecraftProcess::finish(int code, ExitStatus status)
m_prepostlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(code));
// run post-exit
- if (!m_instance->settings().get("PostExitCommand").toString().isEmpty())
+ QString postlaunch_cmd = m_instance->settings().get("PostExitCommand").toString();
+ if (!postlaunch_cmd.isEmpty())
{
- m_prepostlaunchprocess.start(m_instance->settings().get("PostExitCommand").toString());
+ emit log(tr("Running Post-Launch command: %1").arg(postlaunch_cmd));
+ m_prepostlaunchprocess.start(postlaunch_cmd);
m_prepostlaunchprocess.waitForFinished();
+ // Flush console window
+ if (!m_err_leftover.isEmpty())
+ {
+ logOutput(m_err_leftover, MessageLevel::PrePost);
+ m_err_leftover.clear();
+ }
+ if (!m_out_leftover.isEmpty())
+ {
+ logOutput(m_out_leftover, MessageLevel::PrePost);
+ m_out_leftover.clear();
+ }
if (m_prepostlaunchprocess.exitStatus() != NormalExit)
{
+ emit log(tr("Post-Launch command failed with code %1.\n\n").arg(m_prepostlaunchprocess.exitCode()),
+ MessageLevel::Error);
emit postlaunch_failed(m_instance, m_prepostlaunchprocess.exitCode(),
m_prepostlaunchprocess.exitStatus());
}
+ else
+ emit log(tr("Post-Launch command ran successfully.\n\n"));
}
m_instance->cleanupAfterRun();
emit ended(m_instance, code, status);
@@ -175,27 +296,78 @@ void MinecraftProcess::killMinecraft()
void MinecraftProcess::launch()
{
- if (!m_instance->settings().get("PreLaunchCommand").toString().isEmpty())
+ emit log("MultiMC version: " + MMC->version().toString() + "\n\n");
+ emit log("Minecraft folder is:\n" + workingDirectory() + "\n\n");
+
+ QString prelaunch_cmd = m_instance->settings().get("PreLaunchCommand").toString();
+ if (!prelaunch_cmd.isEmpty())
{
- m_prepostlaunchprocess.start(m_instance->settings().get("PreLaunchCommand").toString());
+ // Launch
+ emit log(tr("Running Pre-Launch command: %1").arg(prelaunch_cmd));
+ m_prepostlaunchprocess.start(prelaunch_cmd);
+ // Wait
m_prepostlaunchprocess.waitForFinished();
+ // Flush console window
+ if (!m_err_leftover.isEmpty())
+ {
+ logOutput(m_err_leftover, MessageLevel::PrePost);
+ m_err_leftover.clear();
+ }
+ if (!m_out_leftover.isEmpty())
+ {
+ logOutput(m_out_leftover, MessageLevel::PrePost);
+ m_out_leftover.clear();
+ }
+ // Process return values
if (m_prepostlaunchprocess.exitStatus() != NormalExit)
{
+ emit log(tr("Pre-Launch command failed with code %1.\n\n").arg(m_prepostlaunchprocess.exitCode()),
+ MessageLevel::Fatal);
m_instance->cleanupAfterRun();
emit prelaunch_failed(m_instance, m_prepostlaunchprocess.exitCode(),
m_prepostlaunchprocess.exitStatus());
return;
}
+ else
+ emit log(tr("Pre-Launch command ran successfully.\n\n"));
}
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(m_instance->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("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,21 +376,7 @@ void MinecraftProcess::launch()
emit launch_failed(m_instance);
return;
}
-}
-
-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;
- if (line.contains("[SEVERE]") || line.contains("[STDERR]"))
- level = MessageLevel::Error;
- if (line.contains("[WARNING]"))
- level = MessageLevel::Warning;
- if (line.contains("Exception in thread") || line.contains(" at "))
- level = MessageLevel::Fatal;
- if (line.contains("[DEBUG]"))
- level = MessageLevel::Debug;
- return level;
+ // send the launch script to the launcher part
+ QByteArray bytes = launchScript.toUtf8();
+ writeData(bytes.constData(), bytes.length());
}
diff --git a/logic/MinecraftProcess.h b/logic/MinecraftProcess.h
index bd0151cc..70e5df52 100644
--- a/logic/MinecraftProcess.h
+++ b/logic/MinecraftProcess.h
@@ -18,7 +18,7 @@
#pragma once
#include <QProcess>
-
+#include <QString>
#include "BaseInstance.h"
/**
@@ -31,11 +31,12 @@ enum Enum
{
MultiMC, /**< MultiMC Messages */
Debug, /**< Debug Messages */
- Info, /**< Info Messages */
+ Info, /**< Info Messages */
Message, /**< Standard Messages */
Warning, /**< Warnings */
Error, /**< Errors */
- Fatal /**< Fatal Errors */
+ Fatal, /**< Fatal Errors */
+ PrePost, /**< Pre/Post Launch command output */
};
}
@@ -65,7 +66,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,21 +113,30 @@ 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:
void finish(int, QProcess::ExitStatus status);
void on_stdErr();
void on_stdOut();
+ void on_prepost_stdOut();
+ void on_prepost_stdErr();
+ void logOutput(const QStringList &lines,
+ MessageLevel::Enum defaultLevel = MessageLevel::Message,
+ bool guessLevel = true, bool censor = true);
+ void logOutput(QString line,
+ MessageLevel::Enum defaultLevel = MessageLevel::Message,
+ bool guessLevel = true, bool censor = true);
private:
QString censorPrivateInfo(QString in);
- MessageLevel::Enum getLevel(const QString &message, MessageLevel::Enum defaultLevel);
-
+ MessageLevel::Enum guessLevel(const QString &message, MessageLevel::Enum defaultLevel);
+ MessageLevel::Enum getLevel(const QString &levelName);
};
diff --git a/logic/NagUtils.cpp b/logic/NagUtils.cpp
index 6f81b3c7..c963a98a 100644
--- a/logic/NagUtils.cpp
+++ b/logic/NagUtils.cpp
@@ -23,15 +23,15 @@ void checkJVMArgs(QString jvmargs, QWidget *parent)
if (jvmargs.contains("-XX:PermSize=") || jvmargs.contains(QRegExp("-Xm[sx]")))
{
CustomMessageBox::selectable(
- parent, parent->tr("JVM arguments warning"),
- parent->tr("You tried to manually set a JVM memory option (using "
- " \"-XX:PermSize\", \"-Xmx\" or \"-Xms\") - there"
- " are dedicated boxes for these in the settings (Java"
- " tab, in the Memory group at the top).\n"
- "Your manual settings will be overridden by the"
- " dedicated options.\n"
- "This message will be displayed until you remove them"
- " from the JVM arguments."),
+ parent, QObject::tr("JVM arguments warning"),
+ QObject::tr("You tried to manually set a JVM memory option (using "
+ " \"-XX:PermSize\", \"-Xmx\" or \"-Xms\") - there"
+ " are dedicated boxes for these in the settings (Java"
+ " tab, in the Memory group at the top).\n"
+ "Your manual settings will be overridden by the"
+ " dedicated options.\n"
+ "This message will be displayed until you remove them"
+ " from the JVM arguments."),
QMessageBox::Warning)->exec();
}
}
diff --git a/logic/OneSixFTBInstance.cpp b/logic/OneSixFTBInstance.cpp
index 4bb5cf42..e50a5b53 100644
--- a/logic/OneSixFTBInstance.cpp
+++ b/logic/OneSixFTBInstance.cpp
@@ -92,6 +92,11 @@ OneSixFTBInstance::OneSixFTBInstance(const QString &rootDir, SettingsObject *set
}
}
+QString OneSixFTBInstance::id() const
+{
+ return "FTB/" + BaseInstance::id();
+}
+
QString OneSixFTBInstance::getStatusbarDescription()
{
return "OneSix FTB: " + intendedVersionId();
diff --git a/logic/OneSixFTBInstance.h b/logic/OneSixFTBInstance.h
index 7600090c..dc028819 100644
--- a/logic/OneSixFTBInstance.h
+++ b/logic/OneSixFTBInstance.h
@@ -15,6 +15,8 @@ public:
virtual std::shared_ptr<Task> doUpdate(bool only_prepare) override;
+ virtual QString id() const;
+
private:
std::shared_ptr<OneSixLibrary> m_forge;
};
diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp
index 2392c683..3cfc1c76 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,47 +81,50 @@ 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 && index.isVirtual)
{
- if(index.isVirtual)
- {
- QLOG_INFO() << "Reconstructing virtual assets folder at" << virtualRoot.path();
+ 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);
+ QFile target(target_path);
+
+ QString tlk = asset_object.hash.left(2);
+
+ QString original_path =
+ PathCombine(PathCombine(objectDir.path(), tlk), asset_object.hash);
+ QFile original(original_path);
+ if(!original.exists())
+ continue;
+ if (!target.exists())
{
- AssetObject asset_object = index.objects.value(map);
- QString target_path = PathCombine(virtualRoot.path(), map);
- QFile target(target_path);
-
- QString tlk = asset_object.hash.left(2);
-
- QString original_path = PathCombine(PathCombine(objectDir.path(), tlk), asset_object.hash);
- QFile original(original_path);
- 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());
-
- bool couldCopy = original.copy(target_path);
- QLOG_DEBUG() << " Copying" << original_path << "to" << target_path << QString::number(couldCopy);// << original.errorString();
- }
+ QFileInfo info(target_path);
+ QDir target_dir = info.dir();
+ // 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();
}
-
- // TODO: Write last used time to virtualRoot/.lastused
}
+
+ // TODO: Write last used time to virtualRoot/.lastused
}
return virtualRoot;
@@ -155,7 +161,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 +186,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 " + windowTitle() + "\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/OneSixLibrary.cpp b/logic/OneSixLibrary.cpp
index 4b6ed9dc..d1eceb0e 100644
--- a/logic/OneSixLibrary.cpp
+++ b/logic/OneSixLibrary.cpp
@@ -19,6 +19,9 @@
#include "OneSixRule.h"
#include "OpSys.h"
#include "logic/net/URLConstants.h"
+#include <pathutils.h>
+#include <JlCompress.h>
+#include "logger/QsLog.h"
void OneSixLibrary::finalize()
{
@@ -133,6 +136,90 @@ QString OneSixLibrary::hint()
return m_hint;
}
+bool OneSixLibrary::filesExist()
+{
+ QString storage = storagePath();
+ if (storage.contains("${arch}"))
+ {
+ QString cooked_storage = storage;
+ cooked_storage.replace("${arch}", "32");
+ QFileInfo info32(PathCombine("libraries", cooked_storage));
+ if (!info32.exists())
+ {
+ return false;
+ }
+ cooked_storage = storage;
+ cooked_storage.replace("${arch}", "64");
+ QFileInfo info64(PathCombine("libraries", cooked_storage));
+ if (!info64.exists())
+ {
+ return false;
+ }
+ }
+ else
+ {
+ QFileInfo info(PathCombine("libraries", storage));
+ if (!info.exists())
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool OneSixLibrary::extractTo(QString target_dir)
+{
+ QString storage = storagePath();
+ if (storage.contains("${arch}"))
+ {
+ QString cooked_storage = storage;
+ cooked_storage.replace("${arch}", "32");
+ QString origin = PathCombine("libraries", cooked_storage);
+ QString target_dir_cooked = PathCombine(target_dir, "32");
+ if(!ensureFolderPathExists(target_dir_cooked))
+ {
+ QLOG_ERROR() << "Couldn't create folder " + target_dir_cooked;
+ return false;
+ }
+ if (JlCompress::extractWithExceptions(origin, target_dir_cooked, extract_excludes)
+ .isEmpty())
+ {
+ QLOG_ERROR() << "Couldn't extract " + origin;
+ return false;
+ }
+ cooked_storage = storage;
+ cooked_storage.replace("${arch}", "64");
+ origin = PathCombine("libraries", cooked_storage);
+ target_dir_cooked = PathCombine(target_dir, "32");
+ if(!ensureFolderPathExists(target_dir_cooked))
+ {
+ QLOG_ERROR() << "Couldn't create folder " + target_dir_cooked;
+ return false;
+ }
+ if (JlCompress::extractWithExceptions(origin, target_dir_cooked, extract_excludes)
+ .isEmpty())
+ {
+ QLOG_ERROR() << "Couldn't extract " + origin;
+ return false;
+ }
+ }
+ else
+ {
+ if(!ensureFolderPathExists(target_dir))
+ {
+ QLOG_ERROR() << "Couldn't create folder " + target_dir;
+ return false;
+ }
+ QString path = PathCombine("libraries", storage);
+ if (JlCompress::extractWithExceptions(path, target_dir, extract_excludes).isEmpty())
+ {
+ QLOG_ERROR() << "Couldn't extract " + path;
+ return false;
+ }
+ }
+ return true;
+}
+
QJsonObject OneSixLibrary::toJson()
{
QJsonObject libRoot;
diff --git a/logic/OneSixLibrary.h b/logic/OneSixLibrary.h
index 3f0bc83d..227cdbef 100644
--- a/logic/OneSixLibrary.h
+++ b/logic/OneSixLibrary.h
@@ -126,4 +126,7 @@ public:
/// set a hint about how to treat the library. This is an MMC extension.
void setHint(QString hint);
QString hint();
+
+ bool extractTo(QString target_dir);
+ bool filesExist();
};
diff --git a/logic/OneSixUpdate.cpp b/logic/OneSixUpdate.cpp
index 4d93477a..0119ab07 100644
--- a/logic/OneSixUpdate.cpp
+++ b/logic/OneSixUpdate.cpp
@@ -54,17 +54,7 @@ void OneSixUpdate::executeTask()
if (m_only_prepare)
{
- /*
- * FIXME: in offline mode, do not proceed!
- */
- setStatus(tr("Testing the Java installation..."));
- QString java_path = m_inst->settings().get("JavaPath").toString();
-
- checker.reset(new JavaChecker());
- connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this,
- SLOT(checkFinishedOffline(JavaCheckResult)));
- checker->path = java_path;
- checker->performCheck();
+ prepareForLaunch();
return;
}
@@ -83,46 +73,8 @@ void OneSixUpdate::executeTask()
}
else
{
- checkJavaOnline();
- }
-}
-
-void OneSixUpdate::checkJavaOnline()
-{
- setStatus(tr("Testing the Java installation..."));
- QString java_path = m_inst->settings().get("JavaPath").toString();
-
- checker.reset(new JavaChecker());
- connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this,
- SLOT(checkFinishedOnline(JavaCheckResult)));
- checker->path = java_path;
- checker->performCheck();
-}
-
-void OneSixUpdate::checkFinishedOnline(JavaCheckResult result)
-{
- if (result.valid)
- {
- java_is_64bit = result.is_64bit;
jarlibStart();
}
- else
- {
- emitFailed("The java binary doesn't work. Check the settings and correct the problem");
- }
-}
-
-void OneSixUpdate::checkFinishedOffline(JavaCheckResult result)
-{
- if (result.valid)
- {
- java_is_64bit = result.is_64bit;
- prepareForLaunch();
- }
- else
- {
- emitFailed("The java binary doesn't work. Check the settings and correct the problem");
- }
}
void OneSixUpdate::versionFileStart()
@@ -130,7 +82,8 @@ void OneSixUpdate::versionFileStart()
QLOG_INFO() << m_inst->name() << ": getting version file.";
setStatus(tr("Getting the version files from Mojang..."));
- QString urlstr = "http://" + URLConstants::AWS_DOWNLOAD_VERSIONS + targetVersion->descriptor() + "/" + targetVersion->descriptor() + ".json";
+ QString urlstr = "http://" + URLConstants::AWS_DOWNLOAD_VERSIONS +
+ targetVersion->descriptor() + "/" + targetVersion->descriptor() + ".json";
auto job = new NetJob("Version index");
job->addNetAction(ByteArrayDownload::make(QUrl(urlstr)));
specificVersionDownloadJob.reset(job);
@@ -186,7 +139,7 @@ void OneSixUpdate::versionFileFinished()
}
inst->reloadFullVersion();
- checkJavaOnline();
+ jarlibStart();
}
void OneSixUpdate::versionFileFailed()
@@ -230,7 +183,7 @@ void OneSixUpdate::assetIndexFinished()
{
emitFailed("Failed to read the assets index!");
}
-
+
QList<Md5EtagDownloadPtr> dls;
for (auto object : index.objects.values())
{
@@ -245,17 +198,17 @@ void OneSixUpdate::assetIndexFinished()
dls.append(objectDL);
}
}
- if(dls.size())
+ if (dls.size())
{
setStatus(tr("Getting the assets files from Mojang..."));
auto job = new NetJob("Assets for " + inst->name());
- for(auto dl: dls)
+ for (auto dl : dls)
job->addNetAction(dl);
jarlibDownloadJob.reset(job);
connect(jarlibDownloadJob.get(), SIGNAL(succeeded()), SLOT(assetsFinished()));
connect(jarlibDownloadJob.get(), SIGNAL(failed()), SLOT(assetsFailed()));
connect(jarlibDownloadJob.get(), SIGNAL(progress(qint64, qint64)),
- SIGNAL(progress(qint64, qint64)));
+ SIGNAL(progress(qint64, qint64)));
jarlibDownloadJob->start();
return;
}
@@ -277,8 +230,6 @@ void OneSixUpdate::assetsFailed()
emitFailed("Failed to download assets!");
}
-
-
void OneSixUpdate::jarlibStart()
{
setStatus(tr("Getting the library files from Mojang..."));
@@ -318,24 +269,37 @@ void OneSixUpdate::jarlibStart()
{
if (lib->hint() == "local")
continue;
- QString subst = java_is_64bit ? "64" : "32";
- QString storage = lib->storagePath();
- QString dl = lib->downloadUrl();
- storage.replace("${arch}", subst);
- dl.replace("${arch}", subst);
+ QString raw_storage = lib->storagePath();
+ QString raw_dl = lib->downloadUrl();
- auto entry = metacache->resolveEntry("libraries", storage);
- if (entry->stale)
+ auto f = [&](QString storage, QString dl)
{
- if (lib->hint() == "forge-pack-xz")
+ auto entry = metacache->resolveEntry("libraries", storage);
+ if (entry->stale)
{
- ForgeLibs.append(ForgeXzDownload::make(storage, entry));
- }
- else
- {
- jarlibDownloadJob->addNetAction(CacheDownload::make(dl, entry));
+ if (lib->hint() == "forge-pack-xz")
+ {
+ ForgeLibs.append(ForgeXzDownload::make(storage, entry));
+ }
+ else
+ {
+ jarlibDownloadJob->addNetAction(CacheDownload::make(dl, entry));
+ }
}
+ };
+ if (raw_storage.contains("${arch}"))
+ {
+ QString cooked_storage = raw_storage;
+ QString cooked_dl = raw_dl;
+ f(cooked_storage.replace("${arch}", "32"), cooked_dl.replace("${arch}", "32"));
+ cooked_storage = raw_storage;
+ cooked_dl = raw_dl;
+ f(cooked_storage.replace("${arch}", "64"), cooked_dl.replace("${arch}", "64"));
+ }
+ else
+ {
+ f(raw_storage, raw_dl);
}
}
// TODO: think about how to propagate this from the original json file... or IF AT ALL
@@ -376,7 +340,6 @@ void OneSixUpdate::prepareForLaunch()
// delete any leftovers, if they are present.
onesix_inst->cleanupAfterRun();
- // Acquire swag
QString natives_dir_raw = PathCombine(onesix_inst->instanceRoot(), "natives/");
auto version = onesix_inst->getFullVersion();
if (!version)
@@ -385,38 +348,30 @@ void OneSixUpdate::prepareForLaunch()
"it or changing the version.");
return;
}
- auto libs_to_extract = version->getActiveNativeLibs();
-
- // Acquire bag
- bool success = ensureFolderPathExists(natives_dir_raw);
- if (!success)
- {
- emitFailed("Could not create the native library folder:\n" + natives_dir_raw +
- "\nMake sure MultiMC has appropriate permissions and there is enough space "
- "on the storage device.");
- return;
- }
-
- // Put swag in the bag
- QString subst = java_is_64bit ? "64" : "32";
- for (auto lib : libs_to_extract)
+ /*
+ * emitFailed("Could not create the native library folder:\n" + natives_dir_raw +
+ "\nMake sure MultiMC has appropriate permissions and there is enough
+ space "
+ "on the storage device.");
+ */
+ for (auto lib : version->getActiveNativeLibs())
{
- QString storage = lib->storagePath();
- storage.replace("${arch}", subst);
-
- QString path = "libraries/" + storage;
- QLOG_INFO() << "Will extract " << path.toLocal8Bit();
- if (JlCompress::extractWithExceptions(path, natives_dir_raw, lib->extract_excludes)
- .isEmpty())
+ if (!lib->filesExist())
+ {
+ emitFailed("Native library is missing some files:\n" + lib->storagePath() +
+ "\n\nRun the instance at least once in online mode to get all the "
+ "required files.");
+ return;
+ }
+ if (!lib->extractTo(natives_dir_raw))
{
- emitFailed(
- "Could not extract the native library:\n" + path +
- "\nMake sure MultiMC has appropriate permissions and there is enough space "
- "on the storage device.");
+ emitFailed("Could not extract the native library:\n" + lib->storagePath() + " to " +
+ natives_dir_raw +
+ "\n\nMake sure MultiMC has appropriate permissions and there is enough "
+ "space on the storage device.");
return;
}
}
- // Show them your war face!
emitSucceeded();
}
diff --git a/logic/OneSixUpdate.h b/logic/OneSixUpdate.h
index 00b769c7..bc717a94 100644
--- a/logic/OneSixUpdate.h
+++ b/logic/OneSixUpdate.h
@@ -21,7 +21,6 @@
#include "logic/net/NetJob.h"
#include "logic/tasks/Task.h"
-#include "logic/JavaChecker.h"
class MinecraftVersion;
class BaseInstance;
@@ -50,10 +49,6 @@ slots:
void assetsFinished();
void assetsFailed();
- void checkJavaOnline();
- void checkFinishedOnline(JavaCheckResult result);
- void checkFinishedOffline(JavaCheckResult result);
-
// extract the appropriate libraries
void prepareForLaunch();
@@ -65,7 +60,4 @@ private:
std::shared_ptr<MinecraftVersion> targetVersion;
BaseInstance *m_inst = nullptr;
bool m_only_prepare = false;
- std::shared_ptr<JavaChecker> checker;
-
- bool java_is_64bit = false;
};
diff --git a/logic/SkinUtils.h b/logic/SkinUtils.h
index 324f86b8..64353b72 100644
--- a/logic/SkinUtils.h
+++ b/logic/SkinUtils.h
@@ -19,5 +19,5 @@
namespace SkinUtils
{
-QPixmap getFaceFromCache(QString username, int height = 48, int width = 48);
+QPixmap getFaceFromCache(QString username, int height = 64, int width = 64);
}
diff --git a/logic/auth/MojangAccount.cpp b/logic/auth/MojangAccount.cpp
index a462eda5..f41985ec 100644
--- a/logic/auth/MojangAccount.cpp
+++ b/logic/auth/MojangAccount.cpp
@@ -198,7 +198,11 @@ void MojangAccount::authFailed(QString reason)
{
// This is emitted when the yggdrasil tasks time out or are cancelled.
// -> we treat the error as no-op
- if (reason != "Yggdrasil task cancelled.")
+ if (reason == "Yggdrasil task cancelled.")
+ {
+ // do nothing
+ }
+ else
{
m_online = false;
m_accessToken = QString();
diff --git a/logic/icons/IconList.cpp b/logic/icons/IconList.cpp
index cda2db7b..d76e6fbb 100644
--- a/logic/icons/IconList.cpp
+++ b/logic/icons/IconList.cpp
@@ -336,6 +336,23 @@ QIcon IconList::getIcon(QString key)
return QIcon();
}
+QIcon IconList::getBigIcon(QString key)
+{
+ int icon_index = getIconIndex(key);
+
+ if (icon_index == -1)
+ key = "infinity";
+
+ // Fallback for icons that don't exist.
+ icon_index = getIconIndex(key);
+
+ if (icon_index == -1)
+ return QIcon();
+
+ QPixmap bigone = icons[icon_index].icon().pixmap(256,256).scaled(256,256);
+ return QIcon(bigone);
+}
+
int IconList::getIconIndex(QString key)
{
if (key == "default")
diff --git a/logic/icons/IconList.h b/logic/icons/IconList.h
index 322411d1..4ee3f782 100644
--- a/logic/icons/IconList.h
+++ b/logic/icons/IconList.h
@@ -34,6 +34,7 @@ public:
virtual ~IconList() {};
QIcon getIcon(QString key);
+ QIcon getBigIcon(QString key);
int getIconIndex(QString key);
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
diff --git a/logic/lists/ForgeVersionList.cpp b/logic/lists/ForgeVersionList.cpp
index 56eca744..4902dc64 100644
--- a/logic/lists/ForgeVersionList.cpp
+++ b/logic/lists/ForgeVersionList.cpp
@@ -187,7 +187,7 @@ bool ForgeListLoadTask::parseForgeList(QList<BaseVersionPtr> &out)
QByteArray data;
{
auto dlJob = listDownload;
- auto filename = std::dynamic_pointer_cast<CacheDownload>(dlJob)->m_target_path;
+ auto filename = std::dynamic_pointer_cast<CacheDownload>(dlJob)->getTargetFilepath();
QFile listFile(filename);
if (!listFile.open(QIODevice::ReadOnly))
{
@@ -303,7 +303,7 @@ bool ForgeListLoadTask::parseForgeGradleList(QList<BaseVersionPtr> &out)
QByteArray data;
{
auto dlJob = gradleListDownload;
- auto filename = std::dynamic_pointer_cast<CacheDownload>(dlJob)->m_target_path;
+ auto filename = std::dynamic_pointer_cast<CacheDownload>(dlJob)->getTargetFilepath();
QFile listFile(filename);
if (!listFile.open(QIODevice::ReadOnly))
{
@@ -404,12 +404,8 @@ void ForgeListLoadTask::listDownloaded()
{
return;
}
-
- qSort(list.begin(), list.end(), [](const BaseVersionPtr & p1, const BaseVersionPtr & p2)
- {
- // TODO better comparison (takes major/minor/build number into account)
- return p1->name() > p2->name();
- });
+ std::sort(list.begin(), list.end(), [](const BaseVersionPtr & l, const BaseVersionPtr & r)
+ { return (*l > *r); });
m_list->updateListData(list);
diff --git a/logic/lists/ForgeVersionList.h b/logic/lists/ForgeVersionList.h
index 924084ae..b19d3f56 100644
--- a/logic/lists/ForgeVersionList.h
+++ b/logic/lists/ForgeVersionList.h
@@ -29,25 +29,38 @@ typedef std::shared_ptr<ForgeVersion> ForgeVersionPtr;
struct ForgeVersion : public BaseVersion
{
- virtual QString descriptor()
+ virtual QString descriptor() override
{
return filename;
}
;
- virtual QString name()
+ virtual QString name() override
{
return "Forge " + jobbuildver;
}
;
- virtual QString typeString() const
+ virtual QString typeString() const override
{
if (installer_url.isEmpty())
return "Universal";
else
return "Installer";
}
- ;
+ virtual bool operator<(BaseVersion &a) override
+ {
+ ForgeVersion *pa = dynamic_cast<ForgeVersion *>(&a);
+ if(!pa)
+ return true;
+ return m_buildnr < pa->m_buildnr;
+ }
+ virtual bool operator>(BaseVersion &a) override
+ {
+ ForgeVersion *pa = dynamic_cast<ForgeVersion *>(&a);
+ if(!pa)
+ return false;
+ return m_buildnr > pa->m_buildnr;
+ }
int m_buildnr = 0;
QString universal_url;
QString changelog_url;
diff --git a/logic/lists/InstanceList.cpp b/logic/lists/InstanceList.cpp
index bfd183d9..0d4eab95 100644
--- a/logic/lists/InstanceList.cpp
+++ b/logic/lists/InstanceList.cpp
@@ -308,45 +308,52 @@ void InstanceList::loadForgeInstances(QMap<QString, QString> groupMap)
return;
}
dir.cd("ModPacks");
- auto fpath = dir.absoluteFilePath("modpacks.xml");
- QFile f(fpath);
- QLOG_INFO() << "Discovering FTB instances -- " << fpath;
- if (!f.open(QFile::ReadOnly))
- return;
-
- // read the FTB packs XML.
- QXmlStreamReader reader(&f);
- while (!reader.atEnd())
+ auto allFiles = dir.entryList(QDir::Readable | QDir::Files, QDir::Name);
+ for(auto filename: allFiles)
{
- switch (reader.readNext())
- {
- case QXmlStreamReader::StartElement:
+ if(!filename.endsWith(".xml"))
+ continue;
+ auto fpath = dir.absoluteFilePath(filename);
+ QFile f(fpath);
+ QLOG_INFO() << "Discovering FTB instances -- " << fpath;
+ if (!f.open(QFile::ReadOnly))
+ continue;
+
+ // read the FTB packs XML.
+ QXmlStreamReader reader(&f);
+ while (!reader.atEnd())
{
- if (reader.name() == "modpack")
+ switch (reader.readNext())
{
- QXmlStreamAttributes attrs = reader.attributes();
- FTBRecord record;
- record.dir = attrs.value("dir").toString();
- QDir test(dataDir.absoluteFilePath(record.dir));
- if(!test.exists())
- continue;
- record.name = attrs.value("name").toString();
- record.logo = attrs.value("logo").toString();
- record.mcVersion = attrs.value("mcVersion").toString();
- record.description = attrs.value("description").toString();
- records.append(record);
+ case QXmlStreamReader::StartElement:
+ {
+ if (reader.name() == "modpack")
+ {
+ QXmlStreamAttributes attrs = reader.attributes();
+ FTBRecord record;
+ record.dir = attrs.value("dir").toString();
+ QDir test(dataDir.absoluteFilePath(record.dir));
+ if(!test.exists())
+ continue;
+ record.name = attrs.value("name").toString();
+ record.logo = attrs.value("logo").toString();
+ record.mcVersion = attrs.value("mcVersion").toString();
+ record.description = attrs.value("description").toString();
+ records.append(record);
+ }
+ break;
+ }
+ case QXmlStreamReader::EndElement:
+ break;
+ case QXmlStreamReader::Characters:
+ break;
+ default:
+ break;
}
- break;
- }
- case QXmlStreamReader::EndElement:
- break;
- case QXmlStreamReader::Characters:
- break;
- default:
- break;
}
+ f.close();
}
- f.close();
+
if(!records.size())
{
QLOG_INFO() << "No FTB instances to load.";
diff --git a/logic/net/CacheDownload.cpp b/logic/net/CacheDownload.cpp
index 6eadae39..d2a9bdee 100644
--- a/logic/net/CacheDownload.cpp
+++ b/logic/net/CacheDownload.cpp
@@ -33,25 +33,44 @@ 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;
}
- m_output_file.setFileName(m_target_path);
+ // create a new save file
+ m_output_file.reset(new QSaveFile(m_target_path));
+
// 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;
}
QLOG_INFO() << "Downloading " << m_url.toString();
QNetworkRequest request(m_url);
- if (m_entry->remote_changed_timestamp.size())
- request.setRawHeader(QString("If-Modified-Since").toLatin1(),
- m_entry->remote_changed_timestamp.toLatin1());
- if (m_entry->etag.size())
- request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->etag.toLatin1());
+
+ // check file consistency first.
+ QFile current(m_target_path);
+ if(current.exists() && current.size() != 0)
+ {
+ if (m_entry->remote_changed_timestamp.size())
+ request.setRawHeader(QString("If-Modified-Since").toLatin1(),
+ m_entry->remote_changed_timestamp.toLatin1());
+ if (m_entry->etag.size())
+ request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->etag.toLatin1());
+ }
request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Cached)");
@@ -77,76 +96,74 @@ void CacheDownload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
void CacheDownload::downloadError(QNetworkReply::NetworkError error)
{
// error happened during download.
- QLOG_ERROR() << "Failed" << m_url.toString() << "with reason" << error;
+ QLOG_ERROR() << "Failed " << m_url.toString() << " with reason " << error;
m_status = Job_Failed;
}
void CacheDownload::downloadFinished()
{
// if the download succeeded
- if (m_status != Job_Failed)
+ if (m_status == Job_Failed)
{
+ m_output_file->cancelWriting();
+ m_reply.reset();
+ emit failed(m_index_within_job);
+ return;
+ }
+ // if we wrote any data to the save file, we try to commit the data to the real file.
+ 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;
+ }
+
+ // then get rid of the save file
+ m_output_file.reset();
+
+ 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..154f5988 100644
--- a/logic/net/CacheDownload.h
+++ b/logic/net/CacheDownload.h
@@ -17,29 +17,34 @@
#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
{
Q_OBJECT
-public:
+private:
MetaEntryPtr m_entry;
/// 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;
+ std::shared_ptr<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)
{
return CacheDownloadPtr(new CacheDownload(url, entry));
}
-
+ QString getTargetFilepath()
+ {
+ return m_target_path;
+ }
protected
slots:
virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
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..66f800ae
--- /dev/null
+++ b/logic/status/StatusChecker.cpp
@@ -0,0 +1,137 @@
+/* Copyright 2013 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 "StatusChecker.h"
+
+#include <logic/net/URLConstants.h>
+
+#include <QByteArray>
+#include <QDomDocument>
+
+#include <logger/QsLog.h>
+
+StatusChecker::StatusChecker()
+{
+
+}
+
+void StatusChecker::reloadStatus()
+{
+ if (isLoadingStatus())
+ {
+ // QLOG_INFO() << "Ignored request to reload status. Currently reloading already.";
+ return;
+ }
+
+ // QLOG_INFO() << "Reloading status.";
+
+ NetJob* job = new NetJob("Status JSON");
+ job->addNetAction(ByteArrayDownload::make(URLConstants::MOJANG_STATUS_URL));
+ QObject::connect(job, &NetJob::succeeded, this, &StatusChecker::statusDownloadFinished);
+ QObject::connect(job, &NetJob::failed, this, &StatusChecker::statusDownloadFailed);
+ m_statusNetJob.reset(job);
+ job->start();
+}
+
+void StatusChecker::statusDownloadFinished()
+{
+ QLOG_DEBUG() << "Finished loading status JSON.";
+
+ QByteArray data;
+ {
+ ByteArrayDownloadPtr dl = std::dynamic_pointer_cast<ByteArrayDownload>(m_statusNetJob->first());
+ data = dl->m_data;
+ m_statusNetJob.reset();
+ }
+
+ QJsonParseError jsonError;
+ QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
+
+ if (jsonError.error != QJsonParseError::NoError)
+ {
+ fail("Error parsing status JSON:" + jsonError.errorString());
+ return;
+ }
+
+ if (!jsonDoc.isArray())
+ {
+ fail("Error parsing status JSON: JSON root is not an array");
+ return;
+ }
+
+ QJsonArray root = jsonDoc.array();
+
+ for(auto status = root.begin(); status != root.end(); ++status)
+ {
+ QVariantMap map = (*status).toObject().toVariantMap();
+
+ for (QVariantMap::const_iterator iter = map.begin(); iter != map.end(); ++iter)
+ {
+ QString key = iter.key();
+ QVariant value = iter.value();
+
+ if(value.type() == QVariant::Type::String)
+ {
+ m_statusEntries.insert(key, value.toString());
+ //QLOG_DEBUG() << "Status JSON object: " << key << m_statusEntries[key];
+ }
+ else
+ {
+ fail("Malformed status JSON: expected status type to be a string.");
+ return;
+ }
+ }
+ }
+
+ succeed();
+}
+
+void StatusChecker::statusDownloadFailed()
+{
+ fail("Failed to load status JSON.");
+}
+
+
+QMap<QString, QString> StatusChecker::getStatusEntries() const
+{
+ return m_statusEntries;
+}
+
+bool StatusChecker::isLoadingStatus() const
+{
+ return m_statusNetJob.get() != nullptr;
+}
+
+QString StatusChecker::getLastLoadErrorMsg() const
+{
+ return m_lastLoadError;
+}
+
+void StatusChecker::succeed()
+{
+ m_lastLoadError = "";
+ QLOG_DEBUG() << "Status loading succeeded.";
+ m_statusNetJob.reset();
+ emit statusLoaded();
+}
+
+void StatusChecker::fail(const QString& errorMsg)
+{
+ m_lastLoadError = errorMsg;
+ QLOG_DEBUG() << "Failed to load status:" << errorMsg;
+ m_statusNetJob.reset();
+ emit statusLoadingFailed(errorMsg);
+}
+
diff --git a/logic/status/StatusChecker.h b/logic/status/StatusChecker.h
new file mode 100644
index 00000000..1cb01836
--- /dev/null
+++ b/logic/status/StatusChecker.h
@@ -0,0 +1,57 @@
+/* Copyright 2013 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 <QObject>
+#include <QString>
+#include <QList>
+
+#include <logic/net/NetJob.h>
+
+class StatusChecker : public QObject
+{
+ Q_OBJECT
+public:
+ StatusChecker();
+
+ QString getLastLoadErrorMsg() const;
+
+ bool isStatusLoaded() const;
+
+ bool isLoadingStatus() const;
+
+ QMap<QString, QString> getStatusEntries() const;
+
+ void Q_SLOT reloadStatus();
+
+signals:
+ void statusLoaded();
+ void statusLoadingFailed(QString errorMsg);
+
+protected slots:
+ void statusDownloadFinished();
+ void statusDownloadFailed();
+
+protected:
+ QMap<QString, QString> m_statusEntries;
+ NetJobPtr m_statusNetJob;
+ bool m_loadedStatus;
+ QString m_lastLoadError;
+
+ void Q_SLOT succeed();
+ void Q_SLOT fail(const QString& errorMsg);
+};
+
diff --git a/logic/updater/NotificationChecker.cpp b/logic/updater/NotificationChecker.cpp
index b2d67632..191e90a3 100644
--- a/logic/updater/NotificationChecker.cpp
+++ b/logic/updater/NotificationChecker.cpp
@@ -55,7 +55,7 @@ void NotificationChecker::downloadSucceeded(int)
{
m_entries.clear();
- QFile file(m_download->m_output_file.fileName());
+ QFile file(m_download->getTargetFilepath());
if (file.open(QFile::ReadOnly))
{
QJsonArray root = QJsonDocument::fromJson(file.readAll()).array();
diff --git a/logic/updater/UpdateChecker.cpp b/logic/updater/UpdateChecker.cpp
index 8a280dd1..8e2aa8b3 100644
--- a/logic/updater/UpdateChecker.cpp
+++ b/logic/updater/UpdateChecker.cpp
@@ -30,7 +30,6 @@
UpdateChecker::UpdateChecker()
{
- m_currentChannel = VERSION_CHANNEL;
m_channelListUrl = CHANLIST_URL;
m_updateChecking = false;
m_chanListLoading = false;
diff --git a/logic/updater/UpdateChecker.h b/logic/updater/UpdateChecker.h
index 7840cedc..3b0ee28d 100644
--- a/logic/updater/UpdateChecker.h
+++ b/logic/updater/UpdateChecker.h
@@ -27,7 +27,6 @@ public:
UpdateChecker();
void checkForUpdate(bool notifyNoUpdate);
- void setCurrentChannel(const QString &channel) { m_currentChannel = channel; }
void setChannelListUrl(const QString &url) { m_channelListUrl = url; }
/*!
@@ -83,7 +82,6 @@ private:
QString m_repoUrl;
QString m_channelListUrl;
- QString m_currentChannel;
QList<ChannelListEntry> m_channels;