summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Mrázek <peterix@gmail.com>2016-03-26 16:56:57 +0100
committerPetr Mrázek <peterix@gmail.com>2016-03-27 22:35:06 +0200
commitf032e32133023ed8396fc2b6ead7eadc2816a25b (patch)
tree10ce52261bf06dd9f000896b4e993fb45cd7e3fc
parentd587720010036e3335e321f192449808a75e958b (diff)
downloadMultiMC-f032e32133023ed8396fc2b6ead7eadc2816a25b.tar
MultiMC-f032e32133023ed8396fc2b6ead7eadc2816a25b.tar.gz
MultiMC-f032e32133023ed8396fc2b6ead7eadc2816a25b.tar.lz
MultiMC-f032e32133023ed8396fc2b6ead7eadc2816a25b.tar.xz
MultiMC-f032e32133023ed8396fc2b6ead7eadc2816a25b.zip
NOISSUE finalize support for new mojang version format
-rw-r--r--application/MainWindow.cpp4
-rw-r--r--application/handlers/WebResourceHandler.cpp2
-rw-r--r--application/pages/global/AccountListPage.cpp2
-rw-r--r--depends/launcher/org/multimc/onesix/OneSixLauncher.java40
-rw-r--r--logic/CMakeLists.txt3
-rw-r--r--logic/minecraft/Library.cpp205
-rw-r--r--logic/minecraft/Library.h89
-rw-r--r--logic/minecraft/MinecraftProfile.cpp63
-rw-r--r--logic/minecraft/MinecraftProfile.h9
-rw-r--r--logic/minecraft/MinecraftVersion.cpp2
-rw-r--r--logic/minecraft/MinecraftVersionList.cpp3
-rw-r--r--logic/minecraft/MojangDownloadInfo.h4
-rw-r--r--logic/minecraft/MojangVersionFormat.cpp36
-rw-r--r--logic/minecraft/VersionFile.cpp14
-rw-r--r--logic/minecraft/VersionFile.h4
-rw-r--r--logic/minecraft/forge/ForgeInstaller.cpp14
-rw-r--r--logic/minecraft/forge/ForgeMirror.h10
-rw-r--r--logic/minecraft/forge/ForgeMirrors.cpp118
-rw-r--r--logic/minecraft/forge/ForgeMirrors.h61
-rw-r--r--logic/minecraft/forge/ForgeVersionList.cpp4
-rw-r--r--logic/minecraft/forge/ForgeXzDownload.cpp63
-rw-r--r--logic/minecraft/forge/ForgeXzDownload.h7
-rw-r--r--logic/minecraft/ftb/FTBProfileStrategy.cpp2
-rw-r--r--logic/minecraft/legacy/LegacyUpdate.cpp6
-rw-r--r--logic/minecraft/liteloader/LiteLoaderVersionList.cpp4
-rw-r--r--logic/minecraft/onesix/OneSixInstance.cpp56
-rw-r--r--logic/minecraft/onesix/OneSixProfileStrategy.cpp2
-rw-r--r--logic/minecraft/onesix/OneSixUpdate.cpp67
-rw-r--r--logic/minecraft/onesix/OneSixUpdate.h1
-rw-r--r--logic/minecraft/onesix/OneSixVersionFormat.cpp12
-rw-r--r--logic/net/CacheDownload.cpp21
-rw-r--r--logic/net/HttpMetaCache.cpp34
-rw-r--r--logic/net/HttpMetaCache.h54
-rw-r--r--logic/net/URLConstants.cpp34
-rw-r--r--logic/net/URLConstants.h38
-rw-r--r--logic/notifications/NotificationChecker.cpp2
-rw-r--r--logic/trans/TranslationDownloader.cpp2
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/data/lib-native-arch.json46
-rw-r--r--tests/data/lib-native.json52
-rw-r--r--tests/data/lib-simple.json11
-rw-r--r--tests/tst_Library.cpp195
42 files changed, 795 insertions, 602 deletions
diff --git a/application/MainWindow.cpp b/application/MainWindow.cpp
index 1633cc39..ef758fae 100644
--- a/application/MainWindow.cpp
+++ b/application/MainWindow.cpp
@@ -534,7 +534,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow
auto meta = Env::getInstance().metacache()->resolveEntry("skins", profile.id + ".png");
auto action = CacheDownload::make(QUrl("https://" + URLConstants::SKINS_BASE + profile.id + ".png"), meta);
skin_dls.append(action);
- meta->stale = true;
+ meta->setStale(true);
}
}
if (!skin_dls.isEmpty())
@@ -1028,7 +1028,7 @@ InstancePtr MainWindow::instanceFromZipPack(QString instName, QString instGroup,
{
const QString path = url.host() + '/' + url.path();
auto entry = ENV.metacache()->resolveEntry("general", path);
- entry->stale = true;
+ entry->setStale(true);
CacheDownloadPtr dl = CacheDownload::make(url, entry);
NetJob job(tr("Modpack download"));
job.addNetAction(dl);
diff --git a/application/handlers/WebResourceHandler.cpp b/application/handlers/WebResourceHandler.cpp
index 5e51584b..757b870a 100644
--- a/application/handlers/WebResourceHandler.cpp
+++ b/application/handlers/WebResourceHandler.cpp
@@ -13,7 +13,7 @@ WebResourceHandler::WebResourceHandler(const QString &url)
: QObject(), m_url(url)
{
MetaEntryPtr entry = ENV.metacache()->resolveEntry("icons", url);
- if (!entry->stale)
+ if (!entry->isStale())
{
setResultFromFile(entry->getFullPath());
}
diff --git a/application/pages/global/AccountListPage.cpp b/application/pages/global/AccountListPage.cpp
index 84d317c1..89b853c5 100644
--- a/application/pages/global/AccountListPage.cpp
+++ b/application/pages/global/AccountListPage.cpp
@@ -133,7 +133,7 @@ void AccountListPage::addAccount(const QString &errMsg)
auto action = CacheDownload::make(
QUrl("https://" + URLConstants::SKINS_BASE + profile.id + ".png"), meta);
job->addNetAction(action);
- meta->stale = true;
+ meta->setStale(true);
}
job->start();
diff --git a/depends/launcher/org/multimc/onesix/OneSixLauncher.java b/depends/launcher/org/multimc/onesix/OneSixLauncher.java
index d94d06b0..0d1e2174 100644
--- a/depends/launcher/org/multimc/onesix/OneSixLauncher.java
+++ b/depends/launcher/org/multimc/onesix/OneSixLauncher.java
@@ -31,6 +31,8 @@ public class OneSixLauncher implements Launcher
// parameters, separated from ParamBucket
private List<String> libraries;
private List<String> extlibs;
+ private List<String> extlibs32;
+ private List<String> extlibs64;
private List<String> mcparams;
private List<String> mods;
private List<String> jarmods;
@@ -38,7 +40,7 @@ public class OneSixLauncher implements Launcher
private List<String> traits;
private String appletClass;
private String mainClass;
- private String natives;
+ private String nativePath;
private String userName, sessionId;
private String windowTitle;
private String windowParams;
@@ -54,7 +56,22 @@ public class OneSixLauncher implements Launcher
private void processParams(ParamBucket params) throws NotFoundException
{
libraries = params.all("cp");
- extlibs = params.all("ext");
+ extlibs = params.allSafe("ext", new ArrayList<String>());
+ extlibs32 = params.allSafe("ext32", new ArrayList<String>());
+ extlibs64 = params.allSafe("ext64", new ArrayList<String>());
+
+ // Unify the extracted native libs according to actual system architecture
+ String property = System.getProperty("os.arch");
+ boolean is_64 = property.equalsIgnoreCase("x86_64") || property.equalsIgnoreCase("amd64");
+ if(is_64)
+ {
+ extlibs.addAll(extlibs64);
+ }
+ else
+ {
+ extlibs.addAll(extlibs32);
+ }
+
mcparams = params.allSafe("param", new ArrayList<String>() );
mainClass = params.firstSafe("mainClass", "net.minecraft.client.Minecraft");
appletClass = params.firstSafe("appletClass", "net.minecraft.client.MinecraftApplet");
@@ -62,7 +79,7 @@ public class OneSixLauncher implements Launcher
jarmods = params.allSafe("jarmod", new ArrayList<String>());
coremods = params.allSafe("coremod", new ArrayList<String>());
traits = params.allSafe("traits", new ArrayList<String>());
- natives = params.first("natives");
+ nativePath = params.first("natives");
userName = params.first("userName");
sessionId = params.first("sessionId");
@@ -95,7 +112,7 @@ public class OneSixLauncher implements Launcher
Utils.log();
Utils.log("Native path:");
- Utils.log(" " + natives);
+ Utils.log(" " + nativePath);
Utils.log();
Utils.log("Traits:");
@@ -343,16 +360,13 @@ public class OneSixLauncher implements Launcher
// extract native libs (depending on platform here... java!)
Utils.log("Preparing native libraries...");
- String property = System.getProperty("os.arch");
- boolean is_64 = property.equalsIgnoreCase("x86_64") || property.equalsIgnoreCase("amd64");
for(String extlib: extlibs)
{
try
{
- String cleanlib = extlib.replace("${arch}", is_64 ? "64" : "32");
- File cleanlibf = new File(cleanlib);
- Utils.log("Extracting " + cleanlibf.getName());
- Utils.unzipNatives(cleanlibf, new File(natives));
+ File extlibf = new File(extlib);
+ Utils.log("Extracting " + extlibf.getName());
+ Utils.unzipNatives(extlibf, new File(nativePath));
} catch (IOException e)
{
System.err.println("Failed to extract native library:");
@@ -365,9 +379,9 @@ public class OneSixLauncher implements Launcher
// set the native libs path... the brute force way
try
{
- System.setProperty("java.library.path", natives);
- System.setProperty("org.lwjgl.librarypath", natives);
- System.setProperty("net.java.games.input.librarypath", natives);
+ System.setProperty("java.library.path", nativePath);
+ System.setProperty("org.lwjgl.librarypath", nativePath);
+ System.setProperty("net.java.games.input.librarypath", nativePath);
// by the power of reflection, initialize native libs again. DIRTY!
// this is SO BAD. imagine doing that to ld
Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
diff --git a/logic/CMakeLists.txt b/logic/CMakeLists.txt
index 62a4e738..19236e1b 100644
--- a/logic/CMakeLists.txt
+++ b/logic/CMakeLists.txt
@@ -284,9 +284,6 @@ set(LOGIC_SOURCES
minecraft/forge/ForgeVersion.cpp
minecraft/forge/ForgeVersionList.h
minecraft/forge/ForgeVersionList.cpp
- minecraft/forge/ForgeMirror.h
- minecraft/forge/ForgeMirrors.h
- minecraft/forge/ForgeMirrors.cpp
minecraft/forge/ForgeXzDownload.h
minecraft/forge/ForgeXzDownload.cpp
minecraft/forge/LegacyForge.h
diff --git a/logic/minecraft/Library.cpp b/logic/minecraft/Library.cpp
index 9a1d2cc7..922db84e 100644
--- a/logic/minecraft/Library.cpp
+++ b/logic/minecraft/Library.cpp
@@ -1,57 +1,176 @@
#include "Library.h"
+#include <net/CacheDownload.h>
+#include <minecraft/forge/ForgeXzDownload.h>
+#include <Env.h>
#include <FileSystem.h>
-QStringList Library::files() const
+void Library::getApplicableFiles(OpSys system, QStringList& jar, QStringList& native, QStringList& native32, QStringList& native64) const
{
- QStringList retval;
- QString storage = storageSuffix();
- if (storage.contains("${arch}"))
+ auto actualPath = [&](QString relPath)
{
- QString cooked_storage = storage;
- cooked_storage.replace("${arch}", "32");
- retval.append(cooked_storage);
- cooked_storage = storage;
- cooked_storage.replace("${arch}", "64");
- retval.append(cooked_storage);
+ QFileInfo out(FS::PathCombine(storagePrefix(), relPath));
+ return out.absoluteFilePath();
+ };
+ if(m_mojangDownloads)
+ {
+ if(m_mojangDownloads->artifact)
+ {
+ auto artifact = m_mojangDownloads->artifact;
+ jar += actualPath(artifact->path);
+ }
+ if(!isNative())
+ return;
+ if(m_nativeClassifiers.contains(system))
+ {
+ auto nativeClassifier = m_nativeClassifiers[system];
+ if(nativeClassifier.contains("${arch}"))
+ {
+ auto nat32Classifier = nativeClassifier;
+ nat32Classifier.replace("${arch}", "32");
+ auto nat64Classifier = nativeClassifier;
+ nat64Classifier.replace("${arch}", "64");
+ auto nat32info = m_mojangDownloads->getDownloadInfo(nat32Classifier);
+ if(nat32info)
+ native32 += actualPath(nat32info->path);
+ auto nat64info = m_mojangDownloads->getDownloadInfo(nat64Classifier);
+ if(nat64info)
+ native64 += actualPath(nat64info->path);
+ }
+ else
+ {
+ native += actualPath(m_mojangDownloads->getDownloadInfo(nativeClassifier)->path);
+ }
+ }
}
else
- retval.append(storage);
- return retval;
-}
-
-bool Library::filesExist(const QDir &base) const
-{
- auto libFiles = files();
- for(auto file: libFiles)
{
- QFileInfo info(base, file);
- qWarning() << info.absoluteFilePath() << "doesn't exist";
- if (!info.exists())
- return false;
+ QString raw_storage = storageSuffix(system);
+ if(isNative())
+ {
+ if (raw_storage.contains("${arch}"))
+ {
+ auto nat32Storage = raw_storage;
+ nat32Storage.replace("${arch}", "32");
+ auto nat64Storage = raw_storage;
+ nat64Storage.replace("${arch}", "64");
+ native32 += actualPath(nat32Storage);
+ native64 += actualPath(nat64Storage);
+ }
+ else
+ {
+ native += actualPath(raw_storage);
+ }
+ }
+ else
+ {
+ jar += actualPath(raw_storage);
+ }
}
- return true;
}
-QString Library::url() const
+QList<NetActionPtr> Library::getDownloads(OpSys system, HttpMetaCache * cache, QStringList &failedFiles) const
{
- if (!m_absolute_url.isEmpty())
- {
- return m_absolute_url;
- }
+ QList<NetActionPtr> out;
+ bool isLocal = (hint() == "local");
+ bool isForge = (hint() == "forge-pack-xz");
- if (m_base_url.isEmpty())
+ auto add_download = [&](QString storage, QString dl)
{
- return QString("https://" + URLConstants::LIBRARY_BASE) + storageSuffix();
- }
+ auto entry = cache->resolveEntry("libraries", storage);
+ if (!entry->isStale())
+ return true;
+ if(isLocal)
+ {
+ QFileInfo fileinfo(entry->getFullPath());
+ if(!fileinfo.exists())
+ {
+ failedFiles.append(entry->getFullPath());
+ return false;
+ }
+ return true;
+ }
+ if (isForge)
+ {
+ out.append(ForgeXzDownload::make(storage, entry));
+ }
+ else
+ {
+ out.append(CacheDownload::make(dl, entry));
+ }
+ return true;
+ };
- if(m_base_url.endsWith('/'))
+ if(m_mojangDownloads)
{
- return m_base_url + storageSuffix();
+ if(m_mojangDownloads->artifact)
+ {
+ auto artifact = m_mojangDownloads->artifact;
+ add_download(artifact->path, artifact->url);
+ }
+ if(m_nativeClassifiers.contains(system))
+ {
+ auto nativeClassifier = m_nativeClassifiers[system];
+ if(nativeClassifier.contains("${arch}"))
+ {
+ auto nat32Classifier = nativeClassifier;
+ nat32Classifier.replace("${arch}", "32");
+ auto nat64Classifier = nativeClassifier;
+ nat64Classifier.replace("${arch}", "64");
+ auto nat32info = m_mojangDownloads->getDownloadInfo(nat32Classifier);
+ if(nat32info)
+ add_download(nat32info->path, nat32info->url);
+ auto nat64info = m_mojangDownloads->getDownloadInfo(nat64Classifier);
+ if(nat64info)
+ add_download(nat64info->path, nat64info->url);
+ }
+ else
+ {
+ auto info = m_mojangDownloads->getDownloadInfo(nativeClassifier);
+ if(info)
+ {
+ add_download(info->path, info->url);
+ }
+ }
+ }
}
else
{
- return m_base_url + QChar('/') + storageSuffix();
+ QString raw_storage = storageSuffix(system);
+ auto raw_dl = [&](){
+ if (!m_absoluteURL.isEmpty())
+ {
+ return m_absoluteURL;
+ }
+
+ if (m_repositoryURL.isEmpty())
+ {
+ return QString("https://" + URLConstants::LIBRARY_BASE) + raw_storage;
+ }
+
+ if(m_repositoryURL.endsWith('/'))
+ {
+ return m_repositoryURL + raw_storage;
+ }
+ else
+ {
+ return m_repositoryURL + QChar('/') + raw_storage;
+ }
+ }();
+ if (raw_storage.contains("${arch}"))
+ {
+ QString cooked_storage = raw_storage;
+ QString cooked_dl = raw_dl;
+ add_download(cooked_storage.replace("${arch}", "32"), cooked_dl.replace("${arch}", "32"));
+ cooked_storage = raw_storage;
+ cooked_dl = raw_dl;
+ add_download(cooked_storage.replace("${arch}", "64"), cooked_dl.replace("${arch}", "64"));
+ }
+ else
+ {
+ add_download(raw_storage, raw_dl);
+ }
}
+ return out;
}
bool Library::isActive() const
@@ -74,7 +193,7 @@ bool Library::isActive() const
}
if (isNative())
{
- result = result && m_native_classifiers.contains(currentSystem);
+ result = result && m_nativeClassifiers.contains(currentSystem);
}
return result;
}
@@ -98,7 +217,7 @@ QString Library::storagePrefix() const
return m_storagePrefix;
}
-QString Library::storageSuffix() const
+QString Library::storageSuffix(OpSys system) const
{
// non-native? use only the gradle specifier
if (!isNative())
@@ -108,9 +227,9 @@ QString Library::storageSuffix() const
// otherwise native, override classifiers. Mojang HACK!
GradleSpecifier nativeSpec = m_name;
- if (m_native_classifiers.contains(currentSystem))
+ if (m_nativeClassifiers.contains(system))
{
- nativeSpec.setClassifier(m_native_classifiers[currentSystem]);
+ nativeSpec.setClassifier(m_nativeClassifiers[system]);
}
else
{
@@ -118,13 +237,3 @@ QString Library::storageSuffix() const
}
return nativeSpec.toPath();
}
-
-QString Library::storagePath() const
-{
- return FS::PathCombine(storagePrefix(), storageSuffix());
-}
-
-bool Library::storagePathIsDefault() const
-{
- return m_storagePrefix.isEmpty();
-}
diff --git a/logic/minecraft/Library.h b/logic/minecraft/Library.h
index 35b5cb99..fdce93f3 100644
--- a/logic/minecraft/Library.h
+++ b/logic/minecraft/Library.h
@@ -1,5 +1,6 @@
#pragma once
#include <QString>
+#include <net/NetAction.h>
#include <QPair>
#include <QList>
#include <QStringList>
@@ -12,16 +13,19 @@
#include "minecraft/OpSys.h"
#include "GradleSpecifier.h"
#include "net/URLConstants.h"
+#include "MojangDownloadInfo.h"
+
+#include "multimc_logic_export.h"
-struct MojangLibraryDownloadInfo;
class Library;
typedef std::shared_ptr<Library> LibraryPtr;
-class Library
+class MULTIMC_LOGIC_EXPORT Library
{
friend class OneSixVersionFormat;
friend class MojangVersionFormat;
+ friend class LibraryTest;
public:
Library()
{
@@ -35,13 +39,14 @@ public:
{
auto newlib = std::make_shared<Library>();
newlib->m_name = base->m_name;
- newlib->m_base_url = base->m_base_url;
+ newlib->m_repositoryURL = base->m_repositoryURL;
newlib->m_hint = base->m_hint;
- newlib->m_absolute_url = base->m_absolute_url;
- newlib->extract_excludes = base->extract_excludes;
- newlib->m_native_classifiers = base->m_native_classifiers;
+ newlib->m_absoluteURL = base->m_absoluteURL;
+ newlib->m_extractExcludes = base->m_extractExcludes;
+ newlib->m_nativeClassifiers = base->m_nativeClassifiers;
newlib->m_rules = base->m_rules;
newlib->m_storagePrefix = base->m_storagePrefix;
+ newlib->m_mojangDownloads = base->m_mojangDownloads;
return newlib;
}
@@ -83,45 +88,27 @@ public: /* methods */
/// Returns true if the library is native
bool isNative() const
{
- return m_native_classifiers.size() != 0;
+ return m_nativeClassifiers.size() != 0;
}
void setStoragePrefix(QString prefix = QString());
- /// the default storage prefix used by MultiMC
- static QString defaultStoragePrefix();
-
- bool storagePathIsDefault() const;
-
- /// Get the prefix - root of the storage to be used
- QString storagePrefix() const;
-
- /// Get the relative path where the library should be saved
- QString storageSuffix() const;
-
- /// Get the absolute path where the library should be saved
- QString storagePath() const;
-
/// Set the url base for downloads
- void setBaseUrl(const QString &base_url)
+ void setRepositoryURL(const QString &base_url)
{
- m_base_url = base_url;
+ m_repositoryURL = base_url;
}
- /// List of files this library describes. Required because of platform-specificness of native libs
- QStringList files() const;
-
- /// List Shortcut for checking if all the above files exist
- bool filesExist(const QDir &base) const;
+ void getApplicableFiles(OpSys system, QStringList & jar, QStringList & native, QStringList & native32, QStringList & native64) const;
void setAbsoluteUrl(const QString &absolute_url)
{
- m_absolute_url = absolute_url;
+ m_absoluteURL = absolute_url;
}
- QString absoluteUrl() const
+ void setMojangDownloadInfo(MojangLibraryDownloadInfo::Ptr info)
{
- return m_absolute_url;
+ m_mojangDownloads = info;
}
void setHint(const QString &hint)
@@ -129,11 +116,6 @@ public: /* methods */
m_hint = hint;
}
- QString hint() const
- {
- return m_hint;
- }
-
/// Set the load rules
void setRules(QList<std::shared_ptr<Rule>> rules)
{
@@ -143,22 +125,33 @@ public: /* methods */
/// Returns true if the library should be loaded (or extracted, in case of natives)
bool isActive() const;
- /// Get the URL to download the library from
- QString url() const;
+ // Get a list of downloads for this library
+ QList<NetActionPtr> getDownloads(OpSys system, class HttpMetaCache * cache, QStringList &failedFiles) const;
+
+private: /* methods */
+ /// the default storage prefix used by MultiMC
+ static QString defaultStoragePrefix();
+
+ /// Get the prefix - root of the storage to be used
+ QString storagePrefix() const;
+
+ /// Get the relative path where the library should be saved
+ QString storageSuffix(OpSys system) const;
+
+ QString hint() const
+ {
+ return m_hint;
+ }
protected: /* data */
/// the basic gradle dependency specifier.
GradleSpecifier m_name;
- /// where to store the lib locally
- QString m_storage_path;
- /// is this lib actually active on the current OS?
- bool m_is_active = false;
/// DEPRECATED URL prefix of the maven repo where the file can be downloaded
- QString m_base_url;
+ QString m_repositoryURL;
/// DEPRECATED: MultiMC-specific absolute URL. takes precedence over the implicit maven repo URL, if defined
- QString m_absolute_url;
+ QString m_absoluteURL;
/**
* MultiMC-specific type hint - modifies how the library is treated
@@ -172,13 +165,13 @@ protected: /* data */
QString m_storagePrefix;
/// true if the library had an extract/excludes section (even empty)
- bool applyExcludes = false;
+ bool m_hasExcludes = false;
/// a list of files that shouldn't be extracted from the library
- QStringList extract_excludes;
+ QStringList m_extractExcludes;
/// native suffixes per OS
- QMap<OpSys, QString> m_native_classifiers;
+ QMap<OpSys, QString> m_nativeClassifiers;
/// true if the library had a rules section (even empty)
bool applyRules = false;
@@ -187,5 +180,5 @@ protected: /* data */
QList<std::shared_ptr<Rule>> m_rules;
/// MOJANG: container with Mojang style download info
- std::shared_ptr<MojangLibraryDownloadInfo> m_mojang_downloads;
+ MojangLibraryDownloadInfo::Ptr m_mojangDownloads;
};
diff --git a/logic/minecraft/MinecraftProfile.cpp b/logic/minecraft/MinecraftProfile.cpp
index 71ece012..70d0cee4 100644
--- a/logic/minecraft/MinecraftProfile.cpp
+++ b/logic/minecraft/MinecraftProfile.cpp
@@ -14,6 +14,7 @@
*/
#include <QFile>
+#include <QCryptographicHash>
#include <Version.h>
#include <QDir>
#include <QJsonDocument>
@@ -68,9 +69,9 @@ void MinecraftProfile::clear()
m_mainClass.clear();
m_appletClass.clear();
m_libraries.clear();
- m_nativeLibraries.clear();
m_traits.clear();
m_jarMods.clear();
+ mojangDownloads.clear();
m_problemSeverity = ProblemSeverity::PROBLEM_NONE;
}
@@ -428,6 +429,18 @@ void MinecraftProfile::applyMinecraftAssets(MojangAssetIndexInfo::Ptr assets)
}
}
+void MinecraftProfile::applyMojangDownload(const QString &key, MojangDownloadInfo::Ptr download)
+{
+ if(download)
+ {
+ mojangDownloads[key] = download;
+ }
+ else
+ {
+ mojangDownloads.remove(key);
+ }
+}
+
void MinecraftProfile::applyTraits(const QSet<QString>& traits)
{
this->m_traits.unite(traits);
@@ -466,35 +479,24 @@ static int findLibraryByName(QList<LibraryPtr> haystack, const GradleSpecifier &
void MinecraftProfile::applyLibrary(LibraryPtr library)
{
- auto insert = [&](QList<LibraryPtr> & into)
- {
- // find the library by name.
- const int index = findLibraryByName(into, library->rawName());
- // library not found? just add it.
- if (index < 0)
- {
- into.append(Library::limitedCopy(library));
- return;
- }
- auto existingLibrary = into.at(index);
- // if we are higher it means we should update
- if (Version(library->version()) > Version(existingLibrary->version()))
- {
- auto libraryCopy = Library::limitedCopy(library);
- into.replace(index, libraryCopy);
- }
- };
if(!library->isActive())
{
return;
}
- if(library->isNative())
+ // find the library by name.
+ const int index = findLibraryByName(m_libraries, library->rawName());
+ // library not found? just add it.
+ if (index < 0)
{
- insert(m_nativeLibraries);
+ m_libraries.append(Library::limitedCopy(library));
+ return;
}
- else
+ auto existingLibrary = m_libraries.at(index);
+ // if we are higher it means we should update
+ if (Version(library->version()) > Version(existingLibrary->version()))
{
- insert(m_libraries);
+ auto libraryCopy = Library::limitedCopy(library);
+ m_libraries.replace(index, libraryCopy);
}
}
@@ -571,12 +573,21 @@ const QList<LibraryPtr> & MinecraftProfile::getLibraries() const
return m_libraries;
}
-const QList<LibraryPtr> & MinecraftProfile::getNativeLibraries() const
+QString MinecraftProfile::getMainJarUrl() const
{
- return m_nativeLibraries;
+ auto iter = mojangDownloads.find("client");
+ if(iter != mojangDownloads.end())
+ {
+ // current
+ return iter.value()->url;
+ }
+ else
+ {
+ // legacy fallback
+ return URLConstants::getLegacyJarUrl(getMinecraftVersion());
+ }
}
-
void MinecraftProfile::installJarMods(QStringList selectedFiles)
{
m_strategy->installJarMods(selectedFiles);
diff --git a/logic/minecraft/MinecraftProfile.h b/logic/minecraft/MinecraftProfile.h
index ce0ff3cf..ca9288ad 100644
--- a/logic/minecraft/MinecraftProfile.h
+++ b/logic/minecraft/MinecraftProfile.h
@@ -97,6 +97,7 @@ public: /* application of profile variables from patches */
void applyJarMods(const QList<JarmodPtr> &jarMods);
void applyLibrary(LibraryPtr library);
void applyProblemSeverity(ProblemSeverity severity);
+ void applyMojangDownload(const QString & key, MojangDownloadInfo::Ptr download);
public: /* getters for profile variables */
QString getMinecraftVersion() const;
@@ -109,7 +110,7 @@ public: /* getters for profile variables */
const QStringList & getTweakers() const;
const QList<JarmodPtr> & getJarMods() const;
const QList<LibraryPtr> & getLibraries() const;
- const QList<LibraryPtr> & getNativeLibraries() const;
+ QString getMainJarUrl() const;
bool hasTrait(const QString & trait) const;
ProblemSeverity getProblemSeverity() const;
@@ -139,6 +140,9 @@ private: /* data */
/// Assets type - "legacy" or a version ID
MojangAssetIndexInfo::Ptr m_minecraftAssets;
+ // Mojang: list of 'downloads' - client jar, server jar, windows server exe, maybe more.
+ QMap <QString, std::shared_ptr<MojangDownloadInfo>> mojangDownloads;
+
/**
* arguments that should be used for launching minecraft
*
@@ -159,9 +163,6 @@ private: /* data */
/// the list of libraries
QList<LibraryPtr> m_libraries;
- /// the list of native libraries
- QList<LibraryPtr> m_nativeLibraries;
-
/// traits, collected from all the version files (version files can only add)
QSet<QString> m_traits;
diff --git a/logic/minecraft/MinecraftVersion.cpp b/logic/minecraft/MinecraftVersion.cpp
index a3855481..3167fc4a 100644
--- a/logic/minecraft/MinecraftVersion.cpp
+++ b/logic/minecraft/MinecraftVersion.cpp
@@ -72,10 +72,12 @@ void MinecraftVersion::applyFileTo(MinecraftProfile *profile)
QString MinecraftVersion::getUrl() const
{
+ // legacy fallback
if(m_versionFileURL.isEmpty())
{
return QString("http://") + URLConstants::AWS_DOWNLOAD_VERSIONS + m_descriptor + "/" + m_descriptor + ".json";
}
+ // current
return m_versionFileURL;
}
diff --git a/logic/minecraft/MinecraftVersionList.cpp b/logic/minecraft/MinecraftVersionList.cpp
index 62c588d1..bd679c73 100644
--- a/logic/minecraft/MinecraftVersionList.cpp
+++ b/logic/minecraft/MinecraftVersionList.cpp
@@ -470,8 +470,7 @@ void MCVListVersionUpdateTask::executeTask()
specificVersionDownloadJob.reset(job);
connect(specificVersionDownloadJob.get(), SIGNAL(succeeded()), SLOT(json_downloaded()));
connect(specificVersionDownloadJob.get(), SIGNAL(failed(QString)), SIGNAL(failed(QString)));
- connect(specificVersionDownloadJob.get(), SIGNAL(progress(qint64, qint64)),
- SIGNAL(progress(qint64, qint64)));
+ connect(specificVersionDownloadJob.get(), SIGNAL(progress(qint64, qint64)), SIGNAL(progress(qint64, qint64)));
specificVersionDownloadJob->start();
}
diff --git a/logic/minecraft/MojangDownloadInfo.h b/logic/minecraft/MojangDownloadInfo.h
index d8cd2e6d..1f3306e0 100644
--- a/logic/minecraft/MojangDownloadInfo.h
+++ b/logic/minecraft/MojangDownloadInfo.h
@@ -1,5 +1,6 @@
#pragma once
#include <QString>
+#include <QMap>
#include <memory>
struct MojangDownloadInfo
@@ -22,6 +23,9 @@ struct MojangDownloadInfo
struct MojangLibraryDownloadInfo
{
+ MojangLibraryDownloadInfo(MojangDownloadInfo::Ptr artifact): artifact(artifact) {};
+ MojangLibraryDownloadInfo() {};
+
// types
typedef std::shared_ptr<MojangLibraryDownloadInfo> Ptr;
diff --git a/logic/minecraft/MojangVersionFormat.cpp b/logic/minecraft/MojangVersionFormat.cpp
index 41723493..34129c9e 100644
--- a/logic/minecraft/MojangVersionFormat.cpp
+++ b/logic/minecraft/MojangVersionFormat.cpp
@@ -8,7 +8,7 @@
using namespace Json;
#include "ParseUtils.h"
-static const int CURRENT_MINIMUM_LAUNCHER_VERSION = 14;
+static const int CURRENT_MINIMUM_LAUNCHER_VERSION = 18;
static MojangAssetIndexInfo::Ptr assetIndexFromJson (const QJsonObject &obj);
static MojangDownloadInfo::Ptr downloadInfoFromJson (const QJsonObject &obj);
@@ -130,7 +130,7 @@ QJsonObject assetIndexToJson(MojangAssetIndexInfo::Ptr info)
void MojangVersionFormat::readVersionProperties(const QJsonObject &in, VersionFile *out)
{
- Bits::readString(in, "id", out->id);
+ Bits::readString(in, "id", out->minecraftVersion);
Bits::readString(in, "mainClass", out->mainClass);
Bits::readString(in, "minecraftArguments", out->minecraftArguments);
if(out->minecraftArguments.isEmpty())
@@ -212,7 +212,7 @@ VersionFilePtr MojangVersionFormat::versionFileFromJson(const QJsonDocument &doc
out->name = "Minecraft";
out->fileId = "net.minecraft";
- out->version = out->id;
+ out->version = out->minecraftVersion;
out->filename = filename;
@@ -231,7 +231,7 @@ VersionFilePtr MojangVersionFormat::versionFileFromJson(const QJsonDocument &doc
void MojangVersionFormat::writeVersionProperties(const VersionFile* in, QJsonObject& out)
{
- writeString(out, "id", in->id);
+ writeString(out, "id", in->minecraftVersion);
writeString(out, "mainClass", in->mainClass);
writeString(out, "minecraftArguments", in->minecraftArguments);
writeString(out, "type", in->type);
@@ -294,14 +294,14 @@ LibraryPtr MojangVersionFormat::libraryFromJson(const QJsonObject &libObj, const
}
out->m_name = libObj.value("name").toString();
- Bits::readString(libObj, "url", out->m_base_url);
+ Bits::readString(libObj, "url", out->m_repositoryURL);
if (libObj.contains("extract"))
{
- out->applyExcludes = true;
+ out->m_hasExcludes = true;
auto extractObj = requireObject(libObj.value("extract"));
for (auto excludeVal : requireArray(extractObj.value("exclude")))
{
- out->extract_excludes.append(requireString(excludeVal));
+ out->m_extractExcludes.append(requireString(excludeVal));
}
}
if (libObj.contains("natives"))
@@ -316,7 +316,7 @@ LibraryPtr MojangVersionFormat::libraryFromJson(const QJsonObject &libObj, const
OpSys opSys = OpSys_fromString(it.key());
if (opSys != Os_Other)
{
- out->m_native_classifiers[opSys] = it.value().toString();
+ out->m_nativeClassifiers[opSys] = it.value().toString();
}
}
}
@@ -327,7 +327,7 @@ LibraryPtr MojangVersionFormat::libraryFromJson(const QJsonObject &libObj, const
}
if (libObj.contains("downloads"))
{
- out->m_mojang_downloads = libDownloadInfoFromJson(libObj);
+ out->m_mojangDownloads = libDownloadInfoFromJson(libObj);
}
return out;
}
@@ -336,27 +336,25 @@ QJsonObject MojangVersionFormat::libraryToJson(Library *library)
{
QJsonObject libRoot;
libRoot.insert("name", (QString)library->m_name);
- if (library->m_base_url != "http://" + URLConstants::AWS_DOWNLOAD_LIBRARIES &&
- library->m_base_url != "https://" + URLConstants::AWS_DOWNLOAD_LIBRARIES &&
- library->m_base_url != "https://" + URLConstants::LIBRARY_BASE && !library->m_base_url.isEmpty())
+ if (!library->m_repositoryURL.isEmpty())
{
- libRoot.insert("url", library->m_base_url);
+ libRoot.insert("url", library->m_repositoryURL);
}
if (library->isNative())
{
QJsonObject nativeList;
- auto iter = library->m_native_classifiers.begin();
- while (iter != library->m_native_classifiers.end())
+ auto iter = library->m_nativeClassifiers.begin();
+ while (iter != library->m_nativeClassifiers.end())
{
nativeList.insert(OpSys_toString(iter.key()), iter.value());
iter++;
}
libRoot.insert("natives", nativeList);
- if (library->extract_excludes.size())
+ if (library->m_extractExcludes.size())
{
QJsonArray excludes;
QJsonObject extract;
- for (auto exclude : library->extract_excludes)
+ for (auto exclude : library->m_extractExcludes)
{
excludes.append(exclude);
}
@@ -374,9 +372,9 @@ QJsonObject MojangVersionFormat::libraryToJson(Library *library)
}
libRoot.insert("rules", allRules);
}
- if(library->m_mojang_downloads)
+ if(library->m_mojangDownloads)
{
- auto downloadsObj = libDownloadInfoToJson(library->m_mojang_downloads);
+ auto downloadsObj = libDownloadInfoToJson(library->m_mojangDownloads);
libRoot.insert("downloads", downloadsObj);
}
return libRoot;
diff --git a/logic/minecraft/VersionFile.cpp b/logic/minecraft/VersionFile.cpp
index 451c3c8b..573c4cb4 100644
--- a/logic/minecraft/VersionFile.cpp
+++ b/logic/minecraft/VersionFile.cpp
@@ -25,14 +25,14 @@ bool VersionFile::hasJarMods()
void VersionFile::applyTo(MinecraftProfile *profile)
{
auto theirVersion = profile->getMinecraftVersion();
- if (!theirVersion.isNull() && !mcVersion.isNull())
+ if (!theirVersion.isNull() && !dependsOnMinecraftVersion.isNull())
{
- if (QRegExp(mcVersion, Qt::CaseInsensitive, QRegExp::Wildcard).indexIn(theirVersion) == -1)
+ if (QRegExp(dependsOnMinecraftVersion, Qt::CaseInsensitive, QRegExp::Wildcard).indexIn(theirVersion) == -1)
{
- throw MinecraftVersionMismatch(fileId, mcVersion, theirVersion);
+ throw MinecraftVersionMismatch(fileId, dependsOnMinecraftVersion, theirVersion);
}
}
- profile->applyMinecraftVersion(id);
+ profile->applyMinecraftVersion(minecraftVersion);
profile->applyMainClass(mainClass);
profile->applyAppletClass(appletClass);
profile->applyMinecraftArguments(minecraftArguments);
@@ -51,4 +51,10 @@ void VersionFile::applyTo(MinecraftProfile *profile)
profile->applyLibrary(library);
}
profile->applyProblemSeverity(getProblemSeverity());
+ auto iter = mojangDownloads.begin();
+ while(iter != mojangDownloads.end())
+ {
+ profile->applyMojangDownload(iter.key(), iter.value());
+ iter++;
+ }
}
diff --git a/logic/minecraft/VersionFile.h b/logic/minecraft/VersionFile.h
index 7627cc96..1b692f0f 100644
--- a/logic/minecraft/VersionFile.h
+++ b/logic/minecraft/VersionFile.h
@@ -143,13 +143,13 @@ public: /* data */
QString version;
/// MultiMC: dependency on a Minecraft version
- QString mcVersion;
+ QString dependsOnMinecraftVersion;
/// Mojang: used to version the Mojang version format
int minimumLauncherVersion = -1;
/// Mojang: version of Minecraft this is
- QString id;
+ QString minecraftVersion;
/// Mojang: class to launch Minecraft with
QString mainClass;
diff --git a/logic/minecraft/forge/ForgeInstaller.cpp b/logic/minecraft/forge/ForgeInstaller.cpp
index 7957de0e..155a2cac 100644
--- a/logic/minecraft/forge/ForgeInstaller.cpp
+++ b/logic/minecraft/forge/ForgeInstaller.cpp
@@ -126,8 +126,8 @@ void ForgeInstaller::prepare(const QString &filename, const QString &universalUr
QCryptographicHash md5sum(QCryptographicHash::Md5);
md5sum.addData(data);
- cacheentry->stale = false;
- cacheentry->md5sum = md5sum.result().toHex().constData();
+ cacheentry->setStale(false);
+ cacheentry->setMD5Sum(md5sum.result().toHex().constData());
ENV.metacache()->updateEntry(cacheentry);
}
file.close();
@@ -264,8 +264,8 @@ bool ForgeInstaller::add(OneSixInstance *to)
m_forge_json->name = "Forge";
m_forge_json->fileId = id();
m_forge_json->version = m_forgeVersionString;
- m_forge_json->mcVersion = to->intendedVersionId();
- m_forge_json->id.clear();
+ m_forge_json->dependsOnMinecraftVersion = to->intendedVersionId();
+ m_forge_json->minecraftVersion.clear();
m_forge_json->order = 5;
QSaveFile file(filename(to->instanceRoot()));
@@ -378,16 +378,16 @@ protected:
* This fixes some problems with bad files acquired because of unhandled HTTP redirects
* in old versions of MultiMC.
*/
- if (!entry->stale)
+ if (!entry->isStale())
{
QFileInfo localFile(entry->getFullPath());
if (localFile.size() <= 0x4000)
{
- entry->stale = true;
+ entry->setStale(true);
}
}
- if (entry->stale)
+ if (entry->isStale())
{
NetJob *fjob = new NetJob("Forge download");
fjob->addNetAction(CacheDownload::make(forgeVersion->url(), entry));
diff --git a/logic/minecraft/forge/ForgeMirror.h b/logic/minecraft/forge/ForgeMirror.h
deleted file mode 100644
index 2518dffe..00000000
--- a/logic/minecraft/forge/ForgeMirror.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#pragma once
-#include <QString>
-
-struct ForgeMirror
-{
- QString name;
- QString logo_url;
- QString website_url;
- QString mirror_url;
-}; \ No newline at end of file
diff --git a/logic/minecraft/forge/ForgeMirrors.cpp b/logic/minecraft/forge/ForgeMirrors.cpp
deleted file mode 100644
index a2fc2c62..00000000
--- a/logic/minecraft/forge/ForgeMirrors.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-#include "Env.h"
-#include "ForgeMirrors.h"
-#include <QDebug>
-#include <algorithm>
-#include <random>
-
-ForgeMirrors::ForgeMirrors(QList<ForgeXzDownloadPtr> &libs, NetJobPtr parent_job,
- QString mirrorlist)
-{
- m_libs = libs;
- m_parent_job = parent_job;
- m_url = QUrl(mirrorlist);
- m_status = Job_NotStarted;
-}
-
-void ForgeMirrors::start()
-{
- qDebug() << "Downloading " << m_url.toString();
- QNetworkRequest request(m_url);
- request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Uncached)");
- auto worker = ENV.qnam();
- QNetworkReply *rep = worker->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 ForgeMirrors::downloadError(QNetworkReply::NetworkError error)
-{
- // error happened during download.
- qCritical() << "Error getting URL:" << m_url.toString().toLocal8Bit()
- << "Network error: " << error;
- m_status = Job_Failed;
-}
-
-void ForgeMirrors::downloadFinished()
-{
- // if the download succeeded
- if (m_status != Job_Failed)
- {
- // nothing went wrong... ?
- parseMirrorList();
- return;
- }
- // else the download failed, we use a fixed list
- else
- {
- m_status = Job_Finished;
- m_reply.reset();
- deferToFixedList();
- return;
- }
-}
-
-void ForgeMirrors::deferToFixedList()
-{
- m_mirrors.clear();
- m_mirrors.append(
- {"Minecraft Forge", "http://files.minecraftforge.net/forge_logo.png",
- "http://files.minecraftforge.net/", "http://files.minecraftforge.net/maven/"});
- m_mirrors.append({"Creeper Host",
- "http://files.minecraftforge.net/forge_logo.png",
- "https://www.creeperhost.net/link.php?id=1",
- "http://new.creeperrepo.net/forge/maven/"});
- injectDownloads();
- emit succeeded(m_index_within_job);
-}
-
-void ForgeMirrors::parseMirrorList()
-{
- m_status = Job_Finished;
- auto data = m_reply->readAll();
- m_reply.reset();
- auto dataLines = data.split('\n');
- for(auto line: dataLines)
- {
- auto elements = line.split('!');
- if (elements.size() == 4)
- {
- m_mirrors.append({elements[0],elements[1],elements[2],elements[3]});
- }
- }
- if(!m_mirrors.size())
- deferToFixedList();
- injectDownloads();
- emit succeeded(m_index_within_job);
-}
-
-void ForgeMirrors::injectDownloads()
-{
- // shuffle the mirrors randomly
- std::random_device rd;
- std::mt19937 rng(rd());
- std::shuffle(m_mirrors.begin(), m_mirrors.end(), rng);
-
- // tell parent to download the libs
- for(auto lib: m_libs)
- {
- lib->setMirrors(m_mirrors);
- m_parent_job->addNetAction(lib);
- }
-}
-
-void ForgeMirrors::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
-{
- m_total_progress = bytesTotal;
- m_progress = bytesReceived;
- emit netActionProgress(m_index_within_job, bytesReceived, bytesTotal);
-}
-
-void ForgeMirrors::downloadReadyRead()
-{
-}
diff --git a/logic/minecraft/forge/ForgeMirrors.h b/logic/minecraft/forge/ForgeMirrors.h
deleted file mode 100644
index 0312829b..00000000
--- a/logic/minecraft/forge/ForgeMirrors.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Copyright 2013-2015 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 "ForgeXzDownload.h"
-
-#include "net/NetAction.h"
-#include "net/HttpMetaCache.h"
-#include "net/NetJob.h"
-
-#include <QFile>
-#include <QTemporaryFile>
-
-typedef std::shared_ptr<class ForgeMirrors> ForgeMirrorsPtr;
-
-class ForgeMirrors : public NetAction
-{
- Q_OBJECT
-public:
- QList<ForgeXzDownloadPtr> m_libs;
- NetJobPtr m_parent_job;
- QList<ForgeMirror> m_mirrors;
-
-public:
- explicit ForgeMirrors(QList<ForgeXzDownloadPtr> &libs, NetJobPtr parent_job,
- QString mirrorlist);
- static ForgeMirrorsPtr make(QList<ForgeXzDownloadPtr> &libs, NetJobPtr parent_job,
- QString mirrorlist)
- {
- return ForgeMirrorsPtr(new ForgeMirrors(libs, parent_job, mirrorlist));
- }
- virtual ~ForgeMirrors(){};
-protected
-slots:
- virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
- virtual void downloadError(QNetworkReply::NetworkError error);
- virtual void downloadFinished();
- virtual void downloadReadyRead();
-
-private:
- void parseMirrorList();
- void deferToFixedList();
- void injectDownloads();
-
-public
-slots:
- virtual void start();
-};
diff --git a/logic/minecraft/forge/ForgeVersionList.cpp b/logic/minecraft/forge/ForgeVersionList.cpp
index 9b418310..907672f2 100644
--- a/logic/minecraft/forge/ForgeVersionList.cpp
+++ b/logic/minecraft/forge/ForgeVersionList.cpp
@@ -128,8 +128,8 @@ void ForgeListLoadTask::executeTask()
auto gradleForgeListEntry = ENV.metacache()->resolveEntry("minecraftforge", "json");
// verify by poking the server.
- forgeListEntry->stale = true;
- gradleForgeListEntry->stale = true;
+ forgeListEntry->setStale(true);
+ gradleForgeListEntry->setStale(true);
job->addNetAction(listDownload = CacheDownload::make(QUrl(URLConstants::FORGE_LEGACY_URL),
forgeListEntry));
diff --git a/logic/minecraft/forge/ForgeXzDownload.cpp b/logic/minecraft/forge/ForgeXzDownload.cpp
index 6009e31e..2a47bb26 100644
--- a/logic/minecraft/forge/ForgeXzDownload.cpp
+++ b/logic/minecraft/forge/ForgeXzDownload.cpp
@@ -30,19 +30,13 @@ ForgeXzDownload::ForgeXzDownload(QString relative_path, MetaEntryPtr entry) : Ne
m_pack200_xz_file.setFileTemplate("./dl_temp.XXXXXX");
m_status = Job_NotStarted;
m_url_path = relative_path;
-}
-
-void ForgeXzDownload::setMirrors(QList<ForgeMirror> &mirrors)
-{
- m_mirror_index = 0;
- m_mirrors = mirrors;
- updateUrl();
+ m_url = "http://files.minecraftforge.net/maven/" + m_url_path + ".pack.xz";
}
void ForgeXzDownload::start()
{
m_status = Job_InProgress;
- if (!m_entry->stale)
+ if (!m_entry->isStale())
{
m_status = Job_Finished;
emit succeeded(m_index_within_job);
@@ -55,16 +49,10 @@ void ForgeXzDownload::start()
emit failed(m_index_within_job);
return;
}
- if (m_mirrors.empty())
- {
- 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->etag.toLatin1());
+ request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->getETag().toLatin1());
request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Cached)");
auto worker = ENV.qnam();
@@ -96,44 +84,11 @@ void ForgeXzDownload::downloadError(QNetworkReply::NetworkError error)
void ForgeXzDownload::failAndTryNextMirror()
{
m_status = Job_Failed;
- int next = m_mirror_index + 1;
- if(m_mirrors.size() == next)
- m_mirror_index = 0;
- else
- m_mirror_index = next;
-
- updateUrl();
emit failed(m_index_within_job);
}
-void ForgeXzDownload::updateUrl()
-{
- qDebug() << "Updating URL for " << m_url_path;
- for (auto possible : m_mirrors)
- {
- qDebug() << "Possible: " << possible.name << " : " << possible.mirror_url;
- }
- QString aggregate = m_mirrors[m_mirror_index].mirror_url + m_url_path + ".pack.xz";
- m_url = QUrl(aggregate);
-}
-
void ForgeXzDownload::downloadFinished()
{
- //TEST: defer to other possible mirrors (autofail the first one)
- /*
- qDebug() <<"dl " << index_within_job << " mirror " << m_mirror_index;
- if( m_mirror_index == 0)
- {
- qDebug() <<"dl " << index_within_job << " AUTOFAIL";
- m_status = Job_Failed;
- m_pack200_xz_file.close();
- m_pack200_xz_file.remove();
- m_reply.reset();
- failAndTryNextMirror();
- return;
- }
- */
-
// if the download succeeded
if (m_status != Job_Failed)
{
@@ -372,16 +327,14 @@ void ForgeXzDownload::decompressAndInstall()
failAndTryNextMirror();
return;
}
- m_entry->md5sum = QCryptographicHash::hash(jar_file.readAll(), QCryptographicHash::Md5)
- .toHex()
- .constData();
+ 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->etag = m_reply->rawHeader("ETag").constData();
- m_entry->local_changed_timestamp =
- output_file_info.lastModified().toUTC().toMSecsSinceEpoch();
- m_entry->stale = false;
+ 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();
diff --git a/logic/minecraft/forge/ForgeXzDownload.h b/logic/minecraft/forge/ForgeXzDownload.h
index 45722812..67524405 100644
--- a/logic/minecraft/forge/ForgeXzDownload.h
+++ b/logic/minecraft/forge/ForgeXzDownload.h
@@ -19,7 +19,6 @@
#include "net/HttpMetaCache.h"
#include <QFile>
#include <QTemporaryFile>
-#include "ForgeMirror.h"
typedef std::shared_ptr<class ForgeXzDownload> ForgeXzDownloadPtr;
@@ -32,10 +31,6 @@ public:
QString m_target_path;
/// this is the output file, if any
QTemporaryFile m_pack200_xz_file;
- /// mirror index (NOT OPTICS, I SWEAR)
- int m_mirror_index = 0;
- /// list of mirrors to use. Mirror has the url base
- QList<ForgeMirror> m_mirrors;
/// path relative to the mirror base
QString m_url_path;
@@ -46,7 +41,6 @@ public:
return ForgeXzDownloadPtr(new ForgeXzDownload(relative_path, entry));
}
virtual ~ForgeXzDownload(){};
- void setMirrors(QList<ForgeMirror> & mirrors);
protected
slots:
@@ -62,5 +56,4 @@ slots:
private:
void decompressAndInstall();
void failAndTryNextMirror();
- void updateUrl();
};
diff --git a/logic/minecraft/ftb/FTBProfileStrategy.cpp b/logic/minecraft/ftb/FTBProfileStrategy.cpp
index d43fbf6e..f5faacae 100644
--- a/logic/minecraft/ftb/FTBProfileStrategy.cpp
+++ b/logic/minecraft/ftb/FTBProfileStrategy.cpp
@@ -59,7 +59,7 @@ void FTBProfileStrategy::loadDefaultBuiltinPatches()
auto file = ProfileUtils::parseJsonFile(QFileInfo(mcJson), false);
// adapt the loaded file - the FTB patch file format is different than ours.
- file->id.clear();
+ file->minecraftVersion.clear();
for(auto addLib: file->libraries)
{
addLib->setHint("local");
diff --git a/logic/minecraft/legacy/LegacyUpdate.cpp b/logic/minecraft/legacy/LegacyUpdate.cpp
index af787f8c..2d7e8dd2 100644
--- a/logic/minecraft/legacy/LegacyUpdate.cpp
+++ b/logic/minecraft/legacy/LegacyUpdate.cpp
@@ -367,14 +367,12 @@ void LegacyUpdate::jarStart()
setStatus(tr("Downloading new minecraft.jar ..."));
QString version_id = inst->intendedVersionId();
- QString localPath = version_id + "/" + version_id + ".jar";
- QString urlstr = "http://" + URLConstants::AWS_DOWNLOAD_VERSIONS + localPath;
auto dljob = new NetJob("Minecraft.jar for version " + version_id);
auto metacache = ENV.metacache();
- auto entry = metacache->resolveEntry("versions", localPath);
- dljob->addNetAction(CacheDownload::make(QUrl(urlstr), entry));
+ auto entry = metacache->resolveEntry("versions", URLConstants::getJarPath(version_id));
+ dljob->addNetAction(CacheDownload::make(QUrl(URLConstants::getLegacyJarUrl(version_id)), entry));
connect(dljob, SIGNAL(succeeded()), SLOT(jarFinished()));
connect(dljob, SIGNAL(failed(QString)), SLOT(jarFailed(QString)));
connect(dljob, SIGNAL(progress(qint64, qint64)), SIGNAL(progress(qint64, qint64)));
diff --git a/logic/minecraft/liteloader/LiteLoaderVersionList.cpp b/logic/minecraft/liteloader/LiteLoaderVersionList.cpp
index 42698ccc..b0c9736a 100644
--- a/logic/minecraft/liteloader/LiteLoaderVersionList.cpp
+++ b/logic/minecraft/liteloader/LiteLoaderVersionList.cpp
@@ -144,7 +144,7 @@ void LLListLoadTask::executeTask()
auto liteloaderEntry = ENV.metacache()->resolveEntry("liteloader", "versions.json");
// verify by poking the server.
- liteloaderEntry->stale = true;
+ liteloaderEntry->setStale(true);
job->addNetAction(listDownload = CacheDownload::make(QUrl(URLConstants::LITELOADER_URL),
liteloaderEntry));
@@ -251,7 +251,7 @@ void LLListLoadTask::listDownloaded()
// hack to make liteloader 1.7.10_00 work
if(lib->rawName() == GradleSpecifier("org.ow2.asm:asm-all:5.0.3"))
{
- lib->setBaseUrl("http://repo.maven.apache.org/maven2/");
+ lib->setRepositoryURL("http://repo.maven.apache.org/maven2/");
}
version->libraries.append(lib);
}
diff --git a/logic/minecraft/onesix/OneSixInstance.cpp b/logic/minecraft/onesix/OneSixInstance.cpp
index 328c3b38..8d46eefc 100644
--- a/logic/minecraft/onesix/OneSixInstance.cpp
+++ b/logic/minecraft/onesix/OneSixInstance.cpp
@@ -180,24 +180,6 @@ QString OneSixInstance::createLaunchScript(AuthSessionPtr session)
launchScript += "jarmod " + jarmod->originalName + " (" + jarmod->name + ")\n";
}
- // libraries and class path.
- {
- auto libs = m_profile->getLibraries();
- for (auto lib : libs)
- {
- launchScript += "cp " + QFileInfo(lib->storagePath()).absoluteFilePath() + "\n";
- }
- auto jarMods = getJarMods();
- if (!jarMods.isEmpty())
- {
- launchScript += "cp " + QDir(instanceRoot()).absoluteFilePath("minecraft.jar") + "\n";
- }
- else
- {
- QString relpath = m_profile->getMinecraftVersion() + "/" + m_profile->getMinecraftVersion() + ".jar";
- launchScript += "cp " + versionsPath().absoluteFilePath(relpath) + "\n";
- }
- }
auto mainClass = m_profile->getMainClass();
if (!mainClass.isEmpty())
{
@@ -234,15 +216,43 @@ QString OneSixInstance::createLaunchScript(AuthSessionPtr session)
launchScript += "sessionId " + session->session + "\n";
}
- // native libraries (mostly LWJGL)
+ // libraries and class path.
{
- QDir natives_dir(FS::PathCombine(instanceRoot(), "natives/"));
- for (auto native : m_profile->getNativeLibraries())
+ auto libs = m_profile->getLibraries();
+
+ QStringList jar, native, native32, native64;
+ for (auto lib : libs)
+ {
+ lib->getApplicableFiles(currentSystem, jar, native, native32, native64);
+ }
+ for(auto file: jar)
+ {
+ launchScript += "cp " + file + "\n";
+ }
+ for(auto file: native)
{
- QFileInfo finfo(native->storagePath());
- launchScript += "ext " + finfo.absoluteFilePath() + "\n";
+ launchScript += "ext " + file + "\n";
}
+ for(auto file: native32)
+ {
+ launchScript += "ext32 " + file + "\n";
+ }
+ for(auto file: native64)
+ {
+ launchScript += "ext64 " + file + "\n";
+ }
+ QDir natives_dir(FS::PathCombine(instanceRoot(), "natives/"));
launchScript += "natives " + natives_dir.absolutePath() + "\n";
+ auto jarMods = getJarMods();
+ if (!jarMods.isEmpty())
+ {
+ launchScript += "cp " + QDir(instanceRoot()).absoluteFilePath("minecraft.jar") + "\n";
+ }
+ else
+ {
+ QString relpath = m_profile->getMinecraftVersion() + "/" + m_profile->getMinecraftVersion() + ".jar";
+ launchScript += "cp " + versionsPath().absoluteFilePath(relpath) + "\n";
+ }
}
// traits. including legacyLaunch and others ;)
diff --git a/logic/minecraft/onesix/OneSixProfileStrategy.cpp b/logic/minecraft/onesix/OneSixProfileStrategy.cpp
index aaaa9d97..af42286d 100644
--- a/logic/minecraft/onesix/OneSixProfileStrategy.cpp
+++ b/logic/minecraft/onesix/OneSixProfileStrategy.cpp
@@ -54,7 +54,7 @@ void OneSixProfileStrategy::upgradeDeprecatedFiles()
auto file = ProfileUtils::parseJsonFile(QFileInfo(sourceFile), false);
ProfileUtils::removeLwjglFromPatch(file);
file->fileId = "net.minecraft";
- file->version = file->id;
+ file->version = file->minecraftVersion;
file->name = "Minecraft";
auto data = OneSixVersionFormat::versionFileToJson(file, false).toJson();
QSaveFile newPatchFile(mcJson);
diff --git a/logic/minecraft/onesix/OneSixUpdate.cpp b/logic/minecraft/onesix/OneSixUpdate.cpp
index 10d1e294..1c2cd196 100644
--- a/logic/minecraft/onesix/OneSixUpdate.cpp
+++ b/logic/minecraft/onesix/OneSixUpdate.cpp
@@ -14,6 +14,7 @@
*/
#include "Env.h"
+#include <minecraft/forge/ForgeXzDownload.h>
#include "OneSixUpdate.h"
#include "OneSixInstance.h"
@@ -29,7 +30,6 @@
#include "minecraft/MinecraftVersionList.h"
#include "minecraft/MinecraftProfile.h"
#include "minecraft/Library.h"
-#include "minecraft/forge/ForgeMirrors.h"
#include "net/URLConstants.h"
#include "minecraft/AssetsUtils.h"
#include "Exception.h"
@@ -95,7 +95,7 @@ void OneSixUpdate::assetIndexStart()
auto metacache = ENV.metacache();
auto entry = metacache->resolveEntry("asset_indexes", localPath);
- entry->stale = true;
+ entry->setStale(true);
job->addNetAction(CacheDownload::make(indexUrl, entry));
jarlibDownloadJob.reset(job);
@@ -174,88 +174,41 @@ void OneSixUpdate::jarlibStart()
{
QString version_id = profile->getMinecraftVersion();
QString localPath = version_id + "/" + version_id + ".jar";
- QString urlstr = "http://" + URLConstants::AWS_DOWNLOAD_VERSIONS + localPath;
+ QString urlstr = profile->getMainJarUrl();
auto job = new NetJob(tr("Libraries for instance %1").arg(inst->name()));
auto metacache = ENV.metacache();
auto entry = metacache->resolveEntry("versions", localPath);
job->addNetAction(CacheDownload::make(QUrl(urlstr), entry));
- jarHashOnEntry = entry->md5sum;
-
jarlibDownloadJob.reset(job);
}
- auto libs = profile->getNativeLibraries();
- libs.append(profile->getLibraries());
+ auto libs = profile->getLibraries();
auto metacache = ENV.metacache();
- QList<ForgeXzDownloadPtr> ForgeLibs;
QList<LibraryPtr> brokenLocalLibs;
+ QStringList failedFiles;
for (auto lib : libs)
{
- if (lib->hint() == "local")
- {
- if (!lib->filesExist(m_inst->librariesPath()))
- brokenLocalLibs.append(lib);
- continue;
- }
-
- QString raw_storage = lib->storageSuffix();
- QString raw_dl = lib->url();
-
- auto f = [&](QString storage, QString dl)
- {
- auto entry = metacache->resolveEntry("libraries", storage);
- if (entry->stale)
- {
- 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
+ auto dls = lib->getDownloads(currentSystem, metacache.get(), failedFiles);
+ for(auto dl : dls)
{
- f(raw_storage, raw_dl);
+ jarlibDownloadJob->addNetAction(dl);
}
}
if (!brokenLocalLibs.empty())
{
jarlibDownloadJob.reset();
- QStringList failed;
- for (auto brokenLib : brokenLocalLibs)
- {
- failed.append(brokenLib->files());
- }
- QString failed_all = failed.join("\n");
+
+ QString failed_all = failedFiles.join("\n");
emitFailed(tr("Some libraries marked as 'local' are missing their jar "
"files:\n%1\n\nYou'll have to correct this problem manually. If this is "
"an externally tracked instance, make sure to run it at least once "
"outside of MultiMC.").arg(failed_all));
return;
}
- // TODO: think about how to propagate this from the original json file... or IF AT ALL
- QString forgeMirrorList = "http://files.minecraftforge.net/mirror-brand.list";
- if (!ForgeLibs.empty())
- {
- jarlibDownloadJob->addNetAction(
- ForgeMirrors::make(ForgeLibs, jarlibDownloadJob, forgeMirrorList));
- }
connect(jarlibDownloadJob.get(), SIGNAL(succeeded()), SLOT(jarlibFinished()));
connect(jarlibDownloadJob.get(), &NetJob::failed, this, &OneSixUpdate::jarlibFailed);
diff --git a/logic/minecraft/onesix/OneSixUpdate.h b/logic/minecraft/onesix/OneSixUpdate.h
index 6901e3d6..b5195364 100644
--- a/logic/minecraft/onesix/OneSixUpdate.h
+++ b/logic/minecraft/onesix/OneSixUpdate.h
@@ -63,6 +63,5 @@ private:
std::shared_ptr<Task> versionUpdateTask;
OneSixInstance *m_inst = nullptr;
- QString jarHashOnEntry;
QList<FMLlib> fmlLibsToProcess;
};
diff --git a/logic/minecraft/onesix/OneSixVersionFormat.cpp b/logic/minecraft/onesix/OneSixVersionFormat.cpp
index b5e05b22..49a18563 100644
--- a/logic/minecraft/onesix/OneSixVersionFormat.cpp
+++ b/logic/minecraft/onesix/OneSixVersionFormat.cpp
@@ -19,16 +19,16 @@ LibraryPtr OneSixVersionFormat::libraryFromJson(const QJsonObject &libObj, const
{
LibraryPtr out = MojangVersionFormat::libraryFromJson(libObj, filename);
readString(libObj, "MMC-hint", out->m_hint);
- readString(libObj, "MMC-absulute_url", out->m_absolute_url);
- readString(libObj, "MMC-absoluteUrl", out->m_absolute_url);
+ readString(libObj, "MMC-absulute_url", out->m_absoluteURL);
+ readString(libObj, "MMC-absoluteUrl", out->m_absoluteURL);
return out;
}
QJsonObject OneSixVersionFormat::libraryToJson(Library *library)
{
QJsonObject libRoot = MojangVersionFormat::libraryToJson(library);
- if (library->m_absolute_url.size())
- libRoot.insert("MMC-absoluteUrl", library->m_absolute_url);
+ if (library->m_absoluteURL.size())
+ libRoot.insert("MMC-absoluteUrl", library->m_absoluteURL);
if (library->m_hint.size())
libRoot.insert("MMC-hint", library->m_hint);
return libRoot;
@@ -64,7 +64,7 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
out->name = root.value("name").toString();
out->fileId = root.value("fileId").toString();
out->version = root.value("version").toString();
- out->mcVersion = root.value("mcVersion").toString();
+ out->dependsOnMinecraftVersion = root.value("mcVersion").toString();
out->filename = filename;
MojangVersionFormat::readVersionProperties(root, out.get());
@@ -167,7 +167,7 @@ QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch
writeString(root, "name", patch->name);
writeString(root, "fileId", patch->fileId);
writeString(root, "version", patch->version);
- writeString(root, "mcVersion", patch->mcVersion);
+ writeString(root, "mcVersion", patch->dependsOnMinecraftVersion);
MojangVersionFormat::writeVersionProperties(patch.get(), root);
diff --git a/logic/net/CacheDownload.cpp b/logic/net/CacheDownload.cpp
index 1d48170a..d79feb14 100644
--- a/logic/net/CacheDownload.cpp
+++ b/logic/net/CacheDownload.cpp
@@ -34,7 +34,7 @@ CacheDownload::CacheDownload(QUrl url, MetaEntryPtr entry)
void CacheDownload::start()
{
m_status = Job_InProgress;
- if (!m_entry->stale)
+ if (!m_entry->isStale())
{
m_status = Job_Finished;
emit succeeded(m_index_within_job);
@@ -65,11 +65,11 @@ void CacheDownload::start()
QFile current(m_target_path);
if(current.exists() && current.size() != 0)
{
- if (m_entry->remote_changed_timestamp.size())
+ if (m_entry->getRemoteChangedTimestamp().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());
+ m_entry->getRemoteChangedTimestamp().toLatin1());
+ if (m_entry->getETag().size())
+ request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->getETag().toLatin1());
}
request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Cached)");
@@ -138,7 +138,7 @@ void CacheDownload::downloadFinished()
if (m_output_file->commit())
{
m_status = Job_Finished;
- m_entry->md5sum = md5sum.result().toHex().constData();
+ m_entry->setMD5Sum(md5sum.result().toHex().constData());
}
else
{
@@ -160,14 +160,13 @@ void CacheDownload::downloadFinished()
QFileInfo output_file_info(m_target_path);
- m_entry->etag = m_reply->rawHeader("ETag").constData();
+ m_entry->setETag(m_reply->rawHeader("ETag").constData());
if (m_reply->hasRawHeader("Last-Modified"))
{
- m_entry->remote_changed_timestamp = m_reply->rawHeader("Last-Modified").constData();
+ m_entry->setRemoteChangedTimestamp(m_reply->rawHeader("Last-Modified").constData());
}
- m_entry->local_changed_timestamp =
- output_file_info.lastModified().toUTC().toMSecsSinceEpoch();
- m_entry->stale = false;
+ m_entry->setLocalChangedTimestamp(output_file_info.lastModified().toUTC().toMSecsSinceEpoch());
+ m_entry->setStale(false);
ENV.metacache()->updateEntry(m_entry);
m_reply.reset();
diff --git a/logic/net/HttpMetaCache.cpp b/logic/net/HttpMetaCache.cpp
index 3d6aef0d..68bfa89c 100644
--- a/logic/net/HttpMetaCache.cpp
+++ b/logic/net/HttpMetaCache.cpp
@@ -32,7 +32,7 @@
QString MetaEntry::getFullPath()
{
// FIXME: make local?
- return FS::PathCombine(ENV.metacache()->getBasePath(base), path);
+ return FS::PathCombine(basePath, relativePath);
}
HttpMetaCache::HttpMetaCache(QString path) : QObject()
@@ -65,8 +65,7 @@ MetaEntryPtr HttpMetaCache::getEntry(QString base, QString resource_path)
return MetaEntryPtr();
}
-MetaEntryPtr HttpMetaCache::resolveEntry(QString base, QString resource_path,
- QString expected_etag)
+MetaEntryPtr HttpMetaCache::resolveEntry(QString base, QString resource_path, QString expected_etag)
{
auto entry = getEntry(base, resource_path);
// it's not present? generate a default stale entry
@@ -114,15 +113,16 @@ MetaEntryPtr HttpMetaCache::resolveEntry(QString base, QString resource_path,
}
// entry passed all the checks we cared about.
+ entry->basePath = getBasePath(base);
return entry;
}
bool HttpMetaCache::updateEntry(MetaEntryPtr stale_entry)
{
- if (!m_entries.contains(stale_entry->base))
+ if (!m_entries.contains(stale_entry->baseId))
{
qCritical() << "Cannot add entry with unknown base: "
- << stale_entry->base.toLocal8Bit();
+ << stale_entry->baseId.toLocal8Bit();
return false;
}
if (stale_entry->stale)
@@ -130,7 +130,7 @@ bool HttpMetaCache::updateEntry(MetaEntryPtr stale_entry)
qCritical() << "Cannot add stale entry: " << stale_entry->getFullPath().toLocal8Bit();
return false;
}
- m_entries[stale_entry->base].entry_list[stale_entry->path] = stale_entry;
+ m_entries[stale_entry->baseId].entry_list[stale_entry->relativePath] = stale_entry;
SaveEventually();
return true;
}
@@ -148,9 +148,10 @@ bool HttpMetaCache::evictEntry(MetaEntryPtr entry)
MetaEntryPtr HttpMetaCache::staleEntry(QString base, QString resource_path)
{
- auto foo = new MetaEntry;
- foo->base = base;
- foo->path = resource_path;
+ auto foo = new MetaEntry();
+ foo->baseId = base;
+ foo->basePath = getBasePath(base);
+ foo->relativePath = resource_path;
foo->stale = true;
return MetaEntryPtr(foo);
}
@@ -177,6 +178,9 @@ QString HttpMetaCache::getBasePath(QString base)
void HttpMetaCache::Load()
{
+ if(m_index_file.isNull())
+ return;
+
QFile index(m_index_file);
if (!index.open(QIODevice::ReadOnly))
return;
@@ -206,9 +210,9 @@ void HttpMetaCache::Load()
if (!m_entries.contains(base))
continue;
auto &entrymap = m_entries[base];
- auto foo = new MetaEntry;
- foo->base = base;
- QString path = foo->path = element_obj.value("path").toString();
+ auto foo = new MetaEntry();
+ foo->baseId = base;
+ QString path = foo->relativePath = element_obj.value("path").toString();
foo->md5sum = element_obj.value("md5sum").toString();
foo->etag = element_obj.value("etag").toString();
foo->local_changed_timestamp = element_obj.value("last_changed_timestamp").toDouble();
@@ -229,6 +233,8 @@ void HttpMetaCache::SaveEventually()
void HttpMetaCache::SaveNow()
{
+ if(m_index_file.isNull())
+ return;
QJsonObject toplevel;
toplevel.insert("version", QJsonValue(QString("1")));
QJsonArray entriesArr;
@@ -242,8 +248,8 @@ void HttpMetaCache::SaveNow()
continue;
}
QJsonObject entryObj;
- entryObj.insert("base", QJsonValue(entry->base));
- entryObj.insert("path", QJsonValue(entry->path));
+ entryObj.insert("base", QJsonValue(entry->baseId));
+ entryObj.insert("path", QJsonValue(entry->relativePath));
entryObj.insert("md5sum", QJsonValue(entry->md5sum));
entryObj.insert("etag", QJsonValue(entry->etag));
entryObj.insert("last_changed_timestamp",
diff --git a/logic/net/HttpMetaCache.h b/logic/net/HttpMetaCache.h
index fba3fe5a..7b626c70 100644
--- a/logic/net/HttpMetaCache.h
+++ b/logic/net/HttpMetaCache.h
@@ -23,16 +23,58 @@
class HttpMetaCache;
-struct MULTIMC_LOGIC_EXPORT MetaEntry
+class MULTIMC_LOGIC_EXPORT MetaEntry
{
- QString base;
- QString path;
+friend class HttpMetaCache;
+protected:
+ MetaEntry() {}
+public:
+ bool isStale()
+ {
+ return stale;
+ }
+ void setStale(bool stale)
+ {
+ this->stale = stale;
+ }
+ QString getFullPath();
+ QString getRemoteChangedTimestamp()
+ {
+ return remote_changed_timestamp;
+ }
+ void setRemoteChangedTimestamp(QString remote_changed_timestamp)
+ {
+ this->remote_changed_timestamp = remote_changed_timestamp;
+ }
+ void setLocalChangedTimestamp(qint64 timestamp)
+ {
+ local_changed_timestamp = timestamp;
+ }
+ QString getETag()
+ {
+ return etag;
+ }
+ void setETag(QString etag)
+ {
+ this->etag = etag;
+ }
+ QString getMD5Sum()
+ {
+ return md5sum;
+ }
+ void setMD5Sum(QString md5sum)
+ {
+ this->md5sum = md5sum;
+ }
+protected:
+ QString baseId;
+ QString basePath;
+ QString relativePath;
QString md5sum;
QString etag;
qint64 local_changed_timestamp = 0;
QString remote_changed_timestamp; // QString for now, RFC 2822 encoded time
bool stale = true;
- QString getFullPath();
};
typedef std::shared_ptr<MetaEntry> MetaEntryPtr;
@@ -42,7 +84,7 @@ class MULTIMC_LOGIC_EXPORT HttpMetaCache : public QObject
Q_OBJECT
public:
// supply path to the cache index file
- HttpMetaCache(QString path);
+ HttpMetaCache(QString path = QString());
~HttpMetaCache();
// get the entry solely from the cache
@@ -80,4 +122,4 @@ private:
QMap<QString, EntryMap> m_entries;
QString m_index_file;
QTimer saveBatchingTimer;
-}; \ No newline at end of file
+};
diff --git a/logic/net/URLConstants.cpp b/logic/net/URLConstants.cpp
index 85224767..bd476b2c 100644
--- a/logic/net/URLConstants.cpp
+++ b/logic/net/URLConstants.cpp
@@ -1,24 +1,16 @@
#include "URLConstants.h"
-namespace URLConstants
+
+namespace URLConstants {
+
+QString getLegacyJarUrl(QString version)
{
-const QString AWS_DOWNLOAD_BASE("s3.amazonaws.com/Minecraft.Download/");
-const QString AWS_DOWNLOAD_VERSIONS(AWS_DOWNLOAD_BASE + "versions/");
-const QString AWS_DOWNLOAD_LIBRARIES(AWS_DOWNLOAD_BASE + "libraries/");
-const QString AWS_DOWNLOAD_INDEXES(AWS_DOWNLOAD_BASE + "indexes/");
-const QString ASSETS_BASE("assets.minecraft.net/");
-const QString RESOURCE_BASE("resources.download.minecraft.net/");
-const QString LIBRARY_BASE("libraries.minecraft.net/");
-//const QString SKINS_BASE("skins.minecraft.net/MinecraftSkins/");
-const QString SKINS_BASE("crafatar.com/skins/");
-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");
-const QString LITELOADER_URL("http://dl.liteloader.com/versions/versions.json");
-const QString IMGUR_BASE_URL("https://api.imgur.com/3/");
-const QString FMLLIBS_OUR_BASE_URL("http://files.multimc.org/fmllibs/");
-const QString FMLLIBS_FORGE_BASE_URL("http://files.minecraftforge.net/fmllibs/");
-const QString TRANSLATIONS_BASE_URL("http://files.multimc.org/translations/");
+ return "http://" + AWS_DOWNLOAD_VERSIONS + getJarPath(version);
+}
+
+QString getJarPath(QString version)
+{
+ return version + "/" + version + ".jar";
+}
+
+
}
diff --git a/logic/net/URLConstants.h b/logic/net/URLConstants.h
index b04f44ba..8923ef54 100644
--- a/logic/net/URLConstants.h
+++ b/logic/net/URLConstants.h
@@ -17,26 +17,24 @@
#include <QString>
-#include "multimc_logic_export.h"
-
namespace URLConstants
{
-extern const QString AWS_DOWNLOAD_BASE;
-extern const QString AWS_DOWNLOAD_VERSIONS;
-extern const QString AWS_DOWNLOAD_LIBRARIES;
-extern const QString AWS_DOWNLOAD_INDEXES;
-extern const QString ASSETS_BASE;
-extern const QString RESOURCE_BASE;
-extern const QString LIBRARY_BASE;
-MULTIMC_LOGIC_EXPORT extern const QString SKINS_BASE;
-extern const QString AUTH_BASE;
-extern const QString FORGE_LEGACY_URL;
-extern const QString FORGE_GRADLE_URL;
-extern const QString MOJANG_STATUS_URL;
-extern const QString MOJANG_STATUS_NEWS_URL;
-extern const QString LITELOADER_URL;
-extern const QString IMGUR_BASE_URL;
-extern const QString FMLLIBS_OUR_BASE_URL;
-extern const QString FMLLIBS_FORGE_BASE_URL;
-extern const QString TRANSLATIONS_BASE_URL;
+const QString AWS_DOWNLOAD_VERSIONS("s3.amazonaws.com/Minecraft.Download/versions/");
+const QString RESOURCE_BASE("resources.download.minecraft.net/");
+const QString LIBRARY_BASE("libraries.minecraft.net/");
+//const QString SKINS_BASE("skins.minecraft.net/MinecraftSkins/");
+const QString SKINS_BASE("crafatar.com/skins/");
+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");
+const QString LITELOADER_URL("http://dl.liteloader.com/versions/versions.json");
+const QString IMGUR_BASE_URL("https://api.imgur.com/3/");
+const QString FMLLIBS_OUR_BASE_URL("http://files.multimc.org/fmllibs/");
+const QString FMLLIBS_FORGE_BASE_URL("http://files.minecraftforge.net/fmllibs/");
+const QString TRANSLATIONS_BASE_URL("http://files.multimc.org/translations/");
+
+QString getJarPath(QString version);
+QString getLegacyJarUrl(QString version);
}
diff --git a/logic/notifications/NotificationChecker.cpp b/logic/notifications/NotificationChecker.cpp
index 4e35cacc..ab2570b7 100644
--- a/logic/notifications/NotificationChecker.cpp
+++ b/logic/notifications/NotificationChecker.cpp
@@ -54,7 +54,7 @@ void NotificationChecker::checkForNotifications()
}
m_checkJob.reset(new NetJob("Checking for notifications"));
auto entry = ENV.metacache()->resolveEntry("root", "notifications.json");
- entry->stale = true;
+ entry->setStale(true);
m_checkJob->addNetAction(m_download = CacheDownload::make(m_notificationsUrl, entry));
connect(m_download.get(), &CacheDownload::succeeded, this,
&NotificationChecker::downloadSucceeded);
diff --git a/logic/trans/TranslationDownloader.cpp b/logic/trans/TranslationDownloader.cpp
index 5a9cde12..ee5c1fd2 100644
--- a/logic/trans/TranslationDownloader.cpp
+++ b/logic/trans/TranslationDownloader.cpp
@@ -28,7 +28,7 @@ void TranslationDownloader::indexRecieved()
if (!line.isEmpty())
{
MetaEntryPtr entry = ENV.metacache()->resolveEntry("translations", "mmc_" + line);
- entry->stale = true;
+ entry->setStale(true);
CacheDownloadPtr dl = CacheDownload::make(
QUrl(URLConstants::TRANSLATIONS_BASE_URL + line),
entry);
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 1061f911..67a7a45e 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -27,6 +27,7 @@ add_unit_test(userutils tst_userutils.cpp)
add_unit_test(modutils tst_modutils.cpp)
add_unit_test(inifile tst_inifile.cpp)
add_unit_test(FileSystem tst_FileSystem.cpp)
+add_unit_test(Library tst_Library.cpp)
add_unit_test(UpdateChecker tst_UpdateChecker.cpp)
add_unit_test(DownloadTask tst_DownloadTask.cpp)
add_unit_test(filematchers tst_filematchers.cpp)
diff --git a/tests/data/lib-native-arch.json b/tests/data/lib-native-arch.json
new file mode 100644
index 00000000..a73aac54
--- /dev/null
+++ b/tests/data/lib-native-arch.json
@@ -0,0 +1,46 @@
+{
+ "downloads": {
+ "classifiers": {
+ "natives-osx": {
+ "path": "tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-osx.jar",
+ "sha1": "62503ee712766cf77f97252e5902786fd834b8c5",
+ "size": 418331,
+ "url": "https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-osx.jar"
+ },
+ "natives-windows-32": {
+ "path": "tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-32.jar",
+ "sha1": "7c6affe439099806a4f552da14c42f9d643d8b23",
+ "size": 386792,
+ "url": "https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-32.jar"
+ },
+ "natives-windows-64": {
+ "path": "tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-64.jar",
+ "sha1": "39d0c3d363735b4785598e0e7fbf8297c706a9f9",
+ "size": 463390,
+ "url": "https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-64.jar"
+ }
+ }
+ },
+ "extract": {
+ "exclude": [
+ "META-INF/"
+ ]
+ },
+ "name": "tv.twitch:twitch-platform:5.16",
+ "natives": {
+ "linux": "natives-linux",
+ "osx": "natives-osx",
+ "windows": "natives-windows-${arch}"
+ },
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux"
+ }
+ }
+ ]
+}
diff --git a/tests/data/lib-native.json b/tests/data/lib-native.json
new file mode 100644
index 00000000..0a95b2b9
--- /dev/null
+++ b/tests/data/lib-native.json
@@ -0,0 +1,52 @@
+{
+ "downloads": {
+ "artifact": {
+ "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209.jar",
+ "sha1": "b04f3ee8f5e43fa3b162981b50bb72fe1acabb33",
+ "size": 22,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209.jar"
+ },
+ "classifiers": {
+ "natives-linux": {
+ "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-linux.jar",
+ "sha1": "931074f46c795d2f7b30ed6395df5715cfd7675b",
+ "size": 578680,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-linux.jar"
+ },
+ "natives-osx": {
+ "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar",
+ "sha1": "bcab850f8f487c3f4c4dbabde778bb82bd1a40ed",
+ "size": 426822,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar"
+ },
+ "natives-windows": {
+ "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-windows.jar",
+ "sha1": "b84d5102b9dbfabfeb5e43c7e2828d98a7fc80e0",
+ "size": 613748,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-windows.jar"
+ }
+ }
+ },
+ "extract": {
+ "exclude": [
+ "META-INF/"
+ ]
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.4-nightly-20150209",
+ "natives": {
+ "linux": "natives-linux",
+ "osx": "natives-osx",
+ "windows": "natives-windows"
+ },
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+}
diff --git a/tests/data/lib-simple.json b/tests/data/lib-simple.json
new file mode 100644
index 00000000..3ef0f490
--- /dev/null
+++ b/tests/data/lib-simple.json
@@ -0,0 +1,11 @@
+{
+ "downloads": {
+ "artifact": {
+ "path": "com/paulscode/codecwav/20101023/codecwav-20101023.jar",
+ "sha1": "12f031cfe88fef5c1dd36c563c0a3a69bd7261da",
+ "size": 5618,
+ "url": "https://libraries.minecraft.net/com/paulscode/codecwav/20101023/codecwav-20101023.jar"
+ }
+ },
+ "name": "com.paulscode:codecwav:20101023"
+}
diff --git a/tests/tst_Library.cpp b/tests/tst_Library.cpp
new file mode 100644
index 00000000..b5840261
--- /dev/null
+++ b/tests/tst_Library.cpp
@@ -0,0 +1,195 @@
+#include <QTest>
+#include "TestUtil.h"
+
+#include "minecraft/MojangVersionFormat.h"
+#include "minecraft/onesix/OneSixVersionFormat.h"
+#include "minecraft/Library.h"
+#include "net/HttpMetaCache.h"
+#include "FileSystem.h"
+
+class LibraryTest : public QObject
+{
+ Q_OBJECT
+private:
+ LibraryPtr readMojangJson(const char *file)
+ {
+ auto path = QFINDTESTDATA(file);
+ QFile jsonFile(path);
+ jsonFile.open(QIODevice::ReadOnly);
+ auto data = jsonFile.readAll();
+ jsonFile.close();
+ return MojangVersionFormat::libraryFromJson(QJsonDocument::fromJson(data).object(), file);
+ }
+ // get absolute path to expected storage, assuming default cache prefix
+ QStringList getStorage(QString relative)
+ {
+ return {FS::PathCombine(cache->getBasePath("libraries"), relative)};
+ }
+private
+slots:
+ void initTestCase()
+ {
+ cache.reset(new HttpMetaCache());
+ cache->addBase("libraries", QDir("libraries").absolutePath());
+ }
+ void test_legacy()
+ {
+ Library test("test.package:testname:testversion");
+ QCOMPARE(test.artifactPrefix(), QString("test.package:testname"));
+ QCOMPARE(test.isNative(), false);
+
+ QStringList jar, native, native32, native64;
+ test.getApplicableFiles(currentSystem, jar, native, native32, native64);
+ QCOMPARE(jar, getStorage("test/package/testname/testversion/testname-testversion.jar"));
+ QCOMPARE(native, {});
+ QCOMPARE(native32, {});
+ QCOMPARE(native64, {});
+ }
+ void test_legacy_url()
+ {
+ QStringList failedFiles;
+ Library test("test.package:testname:testversion");
+ test.setRepositoryURL("file://foo/bar");
+ auto downloads = test.getDownloads(currentSystem, cache.get(), failedFiles);
+ QCOMPARE(downloads.size(), 1);
+ QCOMPARE(failedFiles, {});
+ NetActionPtr dl = downloads[0];
+ QCOMPARE(dl->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion.jar"));
+ }
+ void test_legacy_url_local_broken()
+ {
+ Library test("test.package:testname:testversion");
+ QCOMPARE(test.isNative(), false);
+ QStringList failedFiles;
+ test.setHint("local");
+ auto downloads = test.getDownloads(currentSystem, cache.get(), failedFiles);
+ QCOMPARE(downloads.size(), 0);
+ QCOMPARE(failedFiles, getStorage("test/package/testname/testversion/testname-testversion.jar"));
+ }
+ void test_legacy_native()
+ {
+ Library test("test.package:testname:testversion");
+ test.m_nativeClassifiers[OpSys::Os_Linux]="linux";
+ QCOMPARE(test.isNative(), true);
+ test.setRepositoryURL("file://foo/bar");
+ {
+ QStringList jar, native, native32, native64;
+ test.getApplicableFiles(Os_Linux, jar, native, native32, native64);
+ QCOMPARE(jar, {});
+ QCOMPARE(native, getStorage("test/package/testname/testversion/testname-testversion-linux.jar"));
+ QCOMPARE(native32, {});
+ QCOMPARE(native64, {});
+ QStringList failedFiles;
+ auto dls = test.getDownloads(Os_Linux, cache.get(), failedFiles);
+ QCOMPARE(dls.size(), 1);
+ QCOMPARE(failedFiles, {});
+ auto dl = dls[0];
+ QCOMPARE(dl->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-linux.jar"));
+ }
+ }
+ void test_legacy_native_arch()
+ {
+ Library test("test.package:testname:testversion");
+ test.m_nativeClassifiers[OpSys::Os_Linux]="linux-${arch}";
+ test.m_nativeClassifiers[OpSys::Os_OSX]="osx-${arch}";
+ test.m_nativeClassifiers[OpSys::Os_Windows]="windows-${arch}";
+ QCOMPARE(test.isNative(), true);
+ test.setRepositoryURL("file://foo/bar");
+ {
+ QStringList jar, native, native32, native64;
+ test.getApplicableFiles(Os_Linux, jar, native, native32, native64);
+ QCOMPARE(jar, {});
+ QCOMPARE(native, {});
+ QCOMPARE(native32, getStorage("test/package/testname/testversion/testname-testversion-linux-32.jar"));
+ QCOMPARE(native64, getStorage("test/package/testname/testversion/testname-testversion-linux-64.jar"));
+ QStringList failedFiles;
+ auto dls = test.getDownloads(Os_Linux, cache.get(), failedFiles);
+ QCOMPARE(dls.size(), 2);
+ QCOMPARE(failedFiles, {});
+ QCOMPARE(dls[0]->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-linux-32.jar"));
+ QCOMPARE(dls[1]->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-linux-64.jar"));
+ }
+ {
+ QStringList jar, native, native32, native64;
+ test.getApplicableFiles(Os_Windows, jar, native, native32, native64);
+ QCOMPARE(jar, {});
+ QCOMPARE(native, {});
+ QCOMPARE(native32, getStorage("test/package/testname/testversion/testname-testversion-windows-32.jar"));
+ QCOMPARE(native64, getStorage("test/package/testname/testversion/testname-testversion-windows-64.jar"));
+ QStringList failedFiles;
+ auto dls = test.getDownloads(Os_Windows, cache.get(), failedFiles);
+ QCOMPARE(dls.size(), 2);
+ QCOMPARE(failedFiles, {});
+ QCOMPARE(dls[0]->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-windows-32.jar"));
+ QCOMPARE(dls[1]->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-windows-64.jar"));
+ }
+ {
+ QStringList jar, native, native32, native64;
+ test.getApplicableFiles(Os_OSX, jar, native, native32, native64);
+ QCOMPARE(jar, {});
+ QCOMPARE(native, {});
+ QCOMPARE(native32, getStorage("test/package/testname/testversion/testname-testversion-osx-32.jar"));
+ QCOMPARE(native64, getStorage("test/package/testname/testversion/testname-testversion-osx-64.jar"));
+ QStringList failedFiles;
+ auto dls = test.getDownloads(Os_OSX, cache.get(), failedFiles);
+ QCOMPARE(dls.size(), 2);
+ QCOMPARE(failedFiles, {});
+ QCOMPARE(dls[0]->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-osx-32.jar"));
+ QCOMPARE(dls[1]->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-osx-64.jar"));
+ }
+ }
+ void test_onenine()
+ {
+ auto test = readMojangJson("data/lib-simple.json");
+ QStringList jar, native, native32, native64;
+ test->getApplicableFiles(Os_OSX, jar, native, native32, native64);
+ QCOMPARE(jar, getStorage("com/paulscode/codecwav/20101023/codecwav-20101023.jar"));
+ QCOMPARE(native, {});
+ QCOMPARE(native32, {});
+ QCOMPARE(native64, {});
+ QStringList failedFiles;
+ auto dls = test->getDownloads(Os_Linux, cache.get(), failedFiles);
+ QCOMPARE(dls.size(), 1);
+ QCOMPARE(failedFiles, {});
+ QCOMPARE(dls[0]->m_url, QUrl("https://libraries.minecraft.net/com/paulscode/codecwav/20101023/codecwav-20101023.jar"));
+ }
+ void test_onenine_native()
+ {
+ auto test = readMojangJson("data/lib-native.json");
+ QStringList jar, native, native32, native64;
+ test->getApplicableFiles(Os_OSX, jar, native, native32, native64);
+ QCOMPARE(jar, getStorage("org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209.jar"));
+ QCOMPARE(native, getStorage("org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar"));
+ QCOMPARE(native32, {});
+ QCOMPARE(native64, {});
+ QStringList failedFiles;
+ auto dls = test->getDownloads(Os_OSX, cache.get(), failedFiles);
+ QCOMPARE(dls.size(), 2);
+ QCOMPARE(failedFiles, {});
+ QCOMPARE(dls[0]->m_url, QUrl("https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209.jar"));
+ QCOMPARE(dls[1]->m_url, QUrl("https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar"));
+ }
+ void test_onenine_native_arch()
+ {
+ auto test = readMojangJson("data/lib-native-arch.json");
+ QStringList jar, native, native32, native64;
+ test->getApplicableFiles(Os_Windows, jar, native, native32, native64);
+ QCOMPARE(jar, {});
+ QCOMPARE(native, {});
+ QCOMPARE(native32, getStorage("tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-32.jar"));
+ QCOMPARE(native64, getStorage("tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-64.jar"));
+ QStringList failedFiles;
+ auto dls = test->getDownloads(Os_Windows, cache.get(), failedFiles);
+ QCOMPARE(dls.size(), 2);
+ QCOMPARE(failedFiles, {});
+ QCOMPARE(dls[0]->m_url, QUrl("https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-32.jar"));
+ QCOMPARE(dls[1]->m_url, QUrl("https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-64.jar"));
+ }
+private:
+ std::unique_ptr<HttpMetaCache> cache;
+ QString workDir;
+};
+
+QTEST_GUILESS_MAIN(LibraryTest)
+
+#include "tst_Library.moc"