aboutsummaryrefslogtreecommitdiff
path: root/api/logic/minecraft
diff options
context:
space:
mode:
Diffstat (limited to 'api/logic/minecraft')
-rw-r--r--api/logic/minecraft/ComponentUpdateTask.cpp16
-rw-r--r--api/logic/minecraft/LaunchProfile.cpp22
-rw-r--r--api/logic/minecraft/LaunchProfile.h7
-rw-r--r--api/logic/minecraft/Library.cpp31
-rw-r--r--api/logic/minecraft/MinecraftUpdate.cpp1
-rw-r--r--api/logic/minecraft/OneSixVersionFormat.cpp25
-rw-r--r--api/logic/minecraft/VersionFile.cpp6
-rw-r--r--api/logic/minecraft/VersionFile.h3
-rw-r--r--api/logic/minecraft/forge/ForgeXzDownload.cpp393
-rw-r--r--api/logic/minecraft/forge/ForgeXzDownload.h61
-rw-r--r--api/logic/minecraft/mod/ModFolderModel.h4
-rw-r--r--api/logic/minecraft/update/LibrariesTask.cpp1
12 files changed, 79 insertions, 491 deletions
diff --git a/api/logic/minecraft/ComponentUpdateTask.cpp b/api/logic/minecraft/ComponentUpdateTask.cpp
index 15003160..84c0474c 100644
--- a/api/logic/minecraft/ComponentUpdateTask.cpp
+++ b/api/logic/minecraft/ComponentUpdateTask.cpp
@@ -451,13 +451,17 @@ static bool getTrivialComponentChanges(const ComponentIndex & index, const Requi
auto & comp = (*compIter);
if(comp->getVersion() != req.equalsVersion)
{
- if(comp->m_dependencyOnly)
- {
- decision = Decision::VersionNotSame;
- }
- else
- {
+ if(comp->isCustom()) {
decision = Decision::LockedVersionNotSame;
+ } else {
+ if(comp->m_dependencyOnly)
+ {
+ decision = Decision::VersionNotSame;
+ }
+ else
+ {
+ decision = Decision::LockedVersionNotSame;
+ }
}
break;
}
diff --git a/api/logic/minecraft/LaunchProfile.cpp b/api/logic/minecraft/LaunchProfile.cpp
index c39bdf04..41705187 100644
--- a/api/logic/minecraft/LaunchProfile.cpp
+++ b/api/logic/minecraft/LaunchProfile.cpp
@@ -11,6 +11,7 @@ void LaunchProfile::clear()
m_mainClass.clear();
m_appletClass.clear();
m_libraries.clear();
+ m_mavenFiles.clear();
m_traits.clear();
m_jarMods.clear();
m_mainJar.reset();
@@ -157,6 +158,22 @@ void LaunchProfile::applyLibrary(LibraryPtr library)
}
}
+void LaunchProfile::applyMavenFile(LibraryPtr mavenFile)
+{
+ if(!mavenFile->isActive())
+ {
+ return;
+ }
+
+ if(mavenFile->isNative())
+ {
+ return;
+ }
+
+ // unlike libraries, we do not keep only one version or try to dedupe them
+ m_mavenFiles.append(Library::limitedCopy(mavenFile));
+}
+
const LibraryPtr LaunchProfile::getMainJar() const
{
return m_mainJar;
@@ -253,6 +270,11 @@ const QList<LibraryPtr> & LaunchProfile::getNativeLibraries() const
return m_nativeLibraries;
}
+const QList<LibraryPtr> & LaunchProfile::getMavenFiles() const
+{
+ return m_mavenFiles;
+}
+
void LaunchProfile::getLibraryFiles(
const QString& architecture,
QStringList& jars,
diff --git a/api/logic/minecraft/LaunchProfile.h b/api/logic/minecraft/LaunchProfile.h
index 77174079..c1752531 100644
--- a/api/logic/minecraft/LaunchProfile.h
+++ b/api/logic/minecraft/LaunchProfile.h
@@ -20,6 +20,7 @@ public: /* application of profile variables from patches */
void applyJarMods(const QList<LibraryPtr> &jarMods);
void applyMods(const QList<LibraryPtr> &jarMods);
void applyLibrary(LibraryPtr library);
+ void applyMavenFile(LibraryPtr library);
void applyMainJar(LibraryPtr jar);
void applyProblemSeverity(ProblemSeverity severity);
/// clear the profile
@@ -37,6 +38,7 @@ public: /* getters for profile variables */
const QList<LibraryPtr> & getJarMods() const;
const QList<LibraryPtr> & getLibraries() const;
const QList<LibraryPtr> & getNativeLibraries() const;
+ const QList<LibraryPtr> & getMavenFiles() const;
const LibraryPtr getMainJar() const;
void getLibraryFiles(
const QString & architecture,
@@ -79,10 +81,13 @@ private:
/// the list of libraries
QList<LibraryPtr> m_libraries;
+ /// the list of maven files to be placed in the libraries folder, but not acted upon
+ QList<LibraryPtr> m_mavenFiles;
+
/// the main jar
LibraryPtr m_mainJar;
- /// the list of libraries
+ /// the list of native libraries
QList<LibraryPtr> m_nativeLibraries;
/// traits, collected from all the version files (version files can only add)
diff --git a/api/logic/minecraft/Library.cpp b/api/logic/minecraft/Library.cpp
index a56e8110..9ff8dcdc 100644
--- a/api/logic/minecraft/Library.cpp
+++ b/api/logic/minecraft/Library.cpp
@@ -3,7 +3,6 @@
#include <net/Download.h>
#include <net/ChecksumValidator.h>
-#include <minecraft/forge/ForgeXzDownload.h>
#include <Env.h>
#include <FileSystem.h>
@@ -88,26 +87,19 @@ QList< std::shared_ptr< NetAction > > Library::getDownloads(
{
options |= Net::Download::Option::AcceptLocalFiles;
}
- if (isForge())
+
+ if(sha1.size())
{
- qDebug() << "XzDownload for:" << rawName() << "storage:" << storage << "url:" << url;
- out.append(ForgeXzDownload::make(url, storage, entry));
+ auto rawSha1 = QByteArray::fromHex(sha1.toLatin1());
+ auto dl = Net::Download::makeCached(url, entry, options);
+ dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1));
+ qDebug() << "Checksummed Download for:" << rawName() << "storage:" << storage << "url:" << url;
+ out.append(dl);
}
else
{
- if(sha1.size())
- {
- auto rawSha1 = QByteArray::fromHex(sha1.toLatin1());
- auto dl = Net::Download::makeCached(url, entry, options);
- dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1));
- qDebug() << "Checksummed Download for:" << rawName() << "storage:" << storage << "url:" << url;
- out.append(dl);
- }
- else
- {
- out.append(Net::Download::makeCached(url, entry, options));
- qDebug() << "Download for:" << rawName() << "storage:" << storage << "url:" << url;
- }
+ out.append(Net::Download::makeCached(url, entry, options));
+ qDebug() << "Download for:" << rawName() << "storage:" << storage << "url:" << url;
}
return true;
};
@@ -243,11 +235,6 @@ bool Library::isAlwaysStale() const
return m_hint == "always-stale";
}
-bool Library::isForge() const
-{
- return m_hint == "forge-pack-xz";
-}
-
void Library::setStoragePrefix(QString prefix)
{
m_storagePrefix = prefix;
diff --git a/api/logic/minecraft/MinecraftUpdate.cpp b/api/logic/minecraft/MinecraftUpdate.cpp
index 00558e37..f9ff114d 100644
--- a/api/logic/minecraft/MinecraftUpdate.cpp
+++ b/api/logic/minecraft/MinecraftUpdate.cpp
@@ -14,7 +14,6 @@
*/
#include "Env.h"
-#include <minecraft/forge/ForgeXzDownload.h>
#include "MinecraftUpdate.h"
#include "MinecraftInstance.h"
diff --git a/api/logic/minecraft/OneSixVersionFormat.cpp b/api/logic/minecraft/OneSixVersionFormat.cpp
index 6f3b926b..a0b6fd0e 100644
--- a/api/logic/minecraft/OneSixVersionFormat.cpp
+++ b/api/logic/minecraft/OneSixVersionFormat.cpp
@@ -144,14 +144,14 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
}
}
- auto readLibs = [&](const char * which)
+ auto readLibs = [&](const char * which, QList<LibraryPtr> & out)
{
for (auto libVal : requireArray(root.value(which)))
{
QJsonObject libObj = requireObject(libVal);
// parse the library
auto lib = libraryFromJson(libObj, filename);
- out->libraries.append(lib);
+ out.append(lib);
}
};
bool hasPlusLibs = root.contains("+libraries");
@@ -160,16 +160,20 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
{
out->addProblem(ProblemSeverity::Warning,
QObject::tr("Version file has both '+libraries' and 'libraries'. This is no longer supported."));
- readLibs("libraries");
- readLibs("+libraries");
+ readLibs("libraries", out->libraries);
+ readLibs("+libraries", out->libraries);
}
else if (hasLibs)
{
- readLibs("libraries");
+ readLibs("libraries", out->libraries);
}
else if(hasPlusLibs)
{
- readLibs("+libraries");
+ readLibs("+libraries", out->libraries);
+ }
+
+ if(root.contains("mavenFiles")) {
+ readLibs("mavenFiles", out->mavenFiles);
}
// if we have mainJar, just use it
@@ -276,6 +280,15 @@ QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch
}
root.insert("libraries", array);
}
+ if (!patch->mavenFiles.isEmpty())
+ {
+ QJsonArray array;
+ for (auto value: patch->mavenFiles)
+ {
+ array.append(OneSixVersionFormat::libraryToJson(value.get()));
+ }
+ root.insert("mavenFiles", array);
+ }
if (!patch->jarMods.isEmpty())
{
QJsonArray array;
diff --git a/api/logic/minecraft/VersionFile.cpp b/api/logic/minecraft/VersionFile.cpp
index cfb9e504..5bad57e9 100644
--- a/api/logic/minecraft/VersionFile.cpp
+++ b/api/logic/minecraft/VersionFile.cpp
@@ -41,6 +41,10 @@ void VersionFile::applyTo(LaunchProfile *profile)
{
profile->applyLibrary(library);
}
+ for (auto mavenFile : mavenFiles)
+ {
+ profile->applyMavenFile(mavenFile);
+ }
profile->applyProblemSeverity(getProblemSeverity());
}
@@ -53,4 +57,4 @@ void VersionFile::applyTo(LaunchProfile *profile)
throw MinecraftVersionMismatch(uid, dependsOnMinecraftVersion, theirVersion);
}
}
-*/ \ No newline at end of file
+*/
diff --git a/api/logic/minecraft/VersionFile.h b/api/logic/minecraft/VersionFile.h
index 3dc9db96..29ddd0bc 100644
--- a/api/logic/minecraft/VersionFile.h
+++ b/api/logic/minecraft/VersionFile.h
@@ -75,6 +75,9 @@ public: /* data */
/// Mojang: list of libraries to add to the version
QList<LibraryPtr> libraries;
+ /// MultiMC: list of maven files to put in the libraries folder, but not in classpath
+ QList<LibraryPtr> mavenFiles;
+
/// The main jar (Minecraft version library, normally)
LibraryPtr mainJar;
diff --git a/api/logic/minecraft/forge/ForgeXzDownload.cpp b/api/logic/minecraft/forge/ForgeXzDownload.cpp
deleted file mode 100644
index c6465469..00000000
--- a/api/logic/minecraft/forge/ForgeXzDownload.cpp
+++ /dev/null
@@ -1,393 +0,0 @@
-/* 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 "Env.h"
-#include "ForgeXzDownload.h"
-#include <FileSystem.h>
-
-#include <QCryptographicHash>
-#include <QFileInfo>
-#include <QDateTime>
-#include <QDir>
-#include <QDebug>
-
-ForgeXzDownload::ForgeXzDownload(QString url, QString relative_path, MetaEntryPtr entry) : NetAction()
-{
- m_entry = entry;
- m_target_path = entry->getFullPath();
- m_pack200_xz_file.setFileTemplate("./dl_temp.XXXXXX");
- m_status = Job_NotStarted;
- m_url_path = relative_path;
- m_url = url + ".pack.xz";
-}
-
-void ForgeXzDownload::start()
-{
- if(m_status == Job_Aborted)
- {
- qWarning() << "Attempt to start an aborted Download:" << m_url.toString();
- emit aborted(m_index_within_job);
- return;
- }
- m_status = Job_InProgress;
- if (!m_entry->isStale())
- {
- m_status = Job_Finished;
- emit succeeded(m_index_within_job);
- return;
- }
- // can we actually create the real, final file?
- if (!FS::ensureFilePathExists(m_target_path))
- {
- m_status = Job_Failed;
- emit failed(m_index_within_job);
- return;
- }
-
- qDebug() << "Downloading " << m_url.toString();
- QNetworkRequest request(m_url);
- request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->getETag().toLatin1());
- request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Cached)");
-
- QNetworkReply *rep = ENV.qnam().get(request);
-
- m_reply.reset(rep);
- connect(rep, SIGNAL(downloadProgress(qint64, qint64)), SLOT(downloadProgress(qint64, qint64)));
- connect(rep, SIGNAL(finished()), SLOT(downloadFinished()));
- connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(downloadError(QNetworkReply::NetworkError)));
- connect(rep, SIGNAL(readyRead()), SLOT(downloadReadyRead()));
-}
-
-void ForgeXzDownload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
-{
- m_total_progress = bytesTotal;
- m_progress = bytesReceived;
- emit netActionProgress(m_index_within_job, bytesReceived, bytesTotal);
-}
-
-void ForgeXzDownload::downloadError(QNetworkReply::NetworkError error)
-{
- if(error == QNetworkReply::OperationCanceledError)
- {
- qCritical() << "Aborted " << m_url.toString();
- m_status = Job_Aborted;
- }
- else
- {
- // error happened during download.
- qCritical() << "Failed " << m_url.toString() << " with reason " << error;
- m_status = Job_Failed;
- }
-}
-
-void ForgeXzDownload::failAndTryNextMirror()
-{
- m_status = Job_Failed;
- emit failed(m_index_within_job);
-}
-
-void ForgeXzDownload::downloadFinished()
-{
- // if the download succeeded
- if (m_status != Job_Failed && m_status != Job_Aborted)
- {
- // nothing went wrong...
- m_status = Job_Finished;
- if (m_pack200_xz_file.isOpen())
- {
- // we actually downloaded something! process and isntall it
- decompressAndInstall();
- return;
- }
- else
- {
- // something bad happened -- on the local machine!
- m_status = Job_Failed;
- m_pack200_xz_file.remove();
- m_reply.reset();
- emit failed(m_index_within_job);
- return;
- }
- }
- else if(m_status == Job_Aborted)
- {
- m_pack200_xz_file.remove();
- m_reply.reset();
- emit failed(m_index_within_job);
- emit aborted(m_index_within_job);
- return;
- }
- // else the download failed
- else
- {
- m_status = Job_Failed;
- m_pack200_xz_file.close();
- m_pack200_xz_file.remove();
- m_reply.reset();
- failAndTryNextMirror();
- return;
- }
-}
-
-void ForgeXzDownload::downloadReadyRead()
-{
-
- if (!m_pack200_xz_file.isOpen())
- {
- if (!m_pack200_xz_file.open())
- {
- /*
- * Can't open the file... the job failed
- */
- m_reply->abort();
- emit failed(m_index_within_job);
- return;
- }
- }
- m_pack200_xz_file.write(m_reply->readAll());
-}
-
-#include "xz.h"
-#include "unpack200.h"
-#include <stdexcept>
-#include <unistd.h>
-
-const size_t buffer_size = 8196;
-
-// NOTE: once this gets here, it can't be aborted anymore. we don't care.
-void ForgeXzDownload::decompressAndInstall()
-{
- // rewind the downloaded temp file
- m_pack200_xz_file.seek(0);
- // de-xz'd file
- QTemporaryFile pack200_file("./dl_temp.XXXXXX");
- pack200_file.open();
-
- bool xz_success = false;
- // first, de-xz
- {
- uint8_t in[buffer_size];
- uint8_t out[buffer_size];
- struct xz_buf b;
- struct xz_dec *s;
- enum xz_ret ret;
- xz_crc32_init();
- xz_crc64_init();
- s = xz_dec_init(XZ_DYNALLOC, 1 << 26);
- if (s == nullptr)
- {
- xz_dec_end(s);
- failAndTryNextMirror();
- return;
- }
- b.in = in;
- b.in_pos = 0;
- b.in_size = 0;
- b.out = out;
- b.out_pos = 0;
- b.out_size = buffer_size;
- while (!xz_success)
- {
- if (b.in_pos == b.in_size)
- {
- b.in_size = m_pack200_xz_file.read((char *)in, sizeof(in));
- b.in_pos = 0;
- }
-
- ret = xz_dec_run(s, &b);
-
- if (b.out_pos == sizeof(out))
- {
- auto wresult = pack200_file.write((char *)out, b.out_pos);
- if (wresult < 0 || size_t(wresult) != b.out_pos)
- {
- // msg = "Write error\n";
- xz_dec_end(s);
- failAndTryNextMirror();
- return;
- }
-
- b.out_pos = 0;
- }
-
- if (ret == XZ_OK)
- continue;
-
- if (ret == XZ_UNSUPPORTED_CHECK)
- {
- // unsupported check. this is OK, but we should log this
- continue;
- }
-
- auto wresult = pack200_file.write((char *)out, b.out_pos);
- if (wresult < 0 || size_t(wresult) != b.out_pos)
- {
- // write error
- pack200_file.close();
- xz_dec_end(s);
- return;
- }
-
- switch (ret)
- {
- case XZ_STREAM_END:
- xz_dec_end(s);
- xz_success = true;
- break;
-
- case XZ_MEM_ERROR:
- qCritical() << "Memory allocation failed\n";
- xz_dec_end(s);
- failAndTryNextMirror();
- return;
-
- case XZ_MEMLIMIT_ERROR:
- qCritical() << "Memory usage limit reached\n";
- xz_dec_end(s);
- failAndTryNextMirror();
- return;
-
- case XZ_FORMAT_ERROR:
- qCritical() << "Not a .xz file\n";
- xz_dec_end(s);
- failAndTryNextMirror();
- return;
-
- case XZ_OPTIONS_ERROR:
- qCritical() << "Unsupported options in the .xz headers\n";
- xz_dec_end(s);
- failAndTryNextMirror();
- return;
-
- case XZ_DATA_ERROR:
- case XZ_BUF_ERROR:
- qCritical() << "File is corrupt\n";
- xz_dec_end(s);
- failAndTryNextMirror();
- return;
-
- default:
- qCritical() << "Bug!\n";
- xz_dec_end(s);
- failAndTryNextMirror();
- return;
- }
- }
- }
- m_pack200_xz_file.remove();
-
- // revert pack200
- pack200_file.seek(0);
- int handle_in = pack200_file.handle();
- // FIXME: dispose of file handles, pointers and the like. Ideally wrap in objects.
- if(handle_in == -1)
- {
- qCritical() << "Error reopening " << pack200_file.fileName();
- failAndTryNextMirror();
- return;
- }
- int handle_in_dup = dup (handle_in);
- if(handle_in_dup == -1)
- {
- qCritical() << "Error reopening " << pack200_file.fileName();
- failAndTryNextMirror();
- return;
- }
- FILE *file_in = fdopen (handle_in_dup, "rb");
- if(!file_in)
- {
- qCritical() << "Error reopening " << pack200_file.fileName();
- failAndTryNextMirror();
- return;
- }
- QFile qfile_out(m_target_path);
- if(!qfile_out.open(QIODevice::WriteOnly))
- {
- qCritical() << "Error opening " << qfile_out.fileName();
- failAndTryNextMirror();
- return;
- }
- int handle_out = qfile_out.handle();
- if(handle_out == -1)
- {
- qCritical() << "Error opening " << qfile_out.fileName();
- failAndTryNextMirror();
- return;
- }
- int handle_out_dup = dup (handle_out);
- if(handle_out_dup == -1)
- {
- qCritical() << "Error reopening " << qfile_out.fileName();
- failAndTryNextMirror();
- return;
- }
- FILE *file_out = fdopen (handle_out_dup, "wb");
- if(!file_out)
- {
- qCritical() << "Error opening " << qfile_out.fileName();
- failAndTryNextMirror();
- return;
- }
- try
- {
- // NOTE: this takes ownership of both FILE pointers. That's why we duplicate them above.
- unpack_200(file_in, file_out);
- }
- catch (const std::runtime_error &err)
- {
- m_status = Job_Failed;
- qCritical() << "Error unpacking " << pack200_file.fileName() << " : " << err.what();
- QFile f(m_target_path);
- if (f.exists())
- f.remove();
- failAndTryNextMirror();
- return;
- }
- pack200_file.remove();
-
- QFile jar_file(m_target_path);
-
- if (!jar_file.open(QIODevice::ReadOnly))
- {
- jar_file.remove();
- failAndTryNextMirror();
- return;
- }
- auto hash = QCryptographicHash::hash(jar_file.readAll(), QCryptographicHash::Md5);
- m_entry->setMD5Sum(hash.toHex().constData());
- jar_file.close();
-
- QFileInfo output_file_info(m_target_path);
- m_entry->setETag(m_reply->rawHeader("ETag").constData());
- m_entry->setLocalChangedTimestamp(output_file_info.lastModified().toUTC().toMSecsSinceEpoch());
- m_entry->setStale(false);
- ENV.metacache()->updateEntry(m_entry);
-
- m_reply.reset();
- emit succeeded(m_index_within_job);
-}
-
-bool ForgeXzDownload::abort()
-{
- if(m_reply)
- m_reply->abort();
- m_status = Job_Aborted;
- return true;
-}
-
-bool ForgeXzDownload::canAbort()
-{
- return true;
-}
diff --git a/api/logic/minecraft/forge/ForgeXzDownload.h b/api/logic/minecraft/forge/ForgeXzDownload.h
deleted file mode 100644
index 63e75f71..00000000
--- a/api/logic/minecraft/forge/ForgeXzDownload.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* 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 "net/NetAction.h"
-#include "net/HttpMetaCache.h"
-#include <QFile>
-#include <QTemporaryFile>
-
-typedef std::shared_ptr<class ForgeXzDownload> ForgeXzDownloadPtr;
-
-class ForgeXzDownload : public NetAction
-{
- Q_OBJECT
-public:
- 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
- QTemporaryFile m_pack200_xz_file;
- /// path relative to the mirror base
- QString m_url_path;
-
-public:
- explicit ForgeXzDownload(QString url, QString relative_path, MetaEntryPtr entry);
- static ForgeXzDownloadPtr make(QString url, QString relative_path, MetaEntryPtr entry)
- {
- return ForgeXzDownloadPtr(new ForgeXzDownload(url, relative_path, entry));
- }
- virtual ~ForgeXzDownload(){};
- bool canAbort() override;
-
-protected
-slots:
- void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override;
- void downloadError(QNetworkReply::NetworkError error) override;
- void downloadFinished() override;
- void downloadReadyRead() override;
-
-public
-slots:
- void start() override;
- bool abort() override;
-
-private:
- void decompressAndInstall();
- void failAndTryNextMirror();
-};
diff --git a/api/logic/minecraft/mod/ModFolderModel.h b/api/logic/minecraft/mod/ModFolderModel.h
index 8394e405..03c584a9 100644
--- a/api/logic/minecraft/mod/ModFolderModel.h
+++ b/api/logic/minecraft/mod/ModFolderModel.h
@@ -85,6 +85,10 @@ public:
{
return mods[index];
}
+ const Mod &at(size_t index) const
+ {
+ return mods.at(index);
+ }
/// Reloads the mod list and returns true if the list changed.
bool update();
diff --git a/api/logic/minecraft/update/LibrariesTask.cpp b/api/logic/minecraft/update/LibrariesTask.cpp
index 912f492b..a000f77f 100644
--- a/api/logic/minecraft/update/LibrariesTask.cpp
+++ b/api/logic/minecraft/update/LibrariesTask.cpp
@@ -45,6 +45,7 @@ void LibrariesTask::executeTask()
QList<LibraryPtr> libArtifactPool;
libArtifactPool.append(profile->getLibraries());
libArtifactPool.append(profile->getNativeLibraries());
+ libArtifactPool.append(profile->getMavenFiles());
libArtifactPool.append(profile->getMainJar());
processArtifactPool(libArtifactPool, failedLocalLibraries, inst->getLocalLibraryPath());