diff options
| author | Petr Mrázek <peterix@gmail.com> | 2016-03-26 16:56:57 +0100 |
|---|---|---|
| committer | Petr Mrázek <peterix@gmail.com> | 2016-03-27 22:35:06 +0200 |
| commit | f032e32133023ed8396fc2b6ead7eadc2816a25b (patch) | |
| tree | 10ce52261bf06dd9f000896b4e993fb45cd7e3fc | |
| parent | d587720010036e3335e321f192449808a75e958b (diff) | |
| download | PrismLauncher-f032e32133023ed8396fc2b6ead7eadc2816a25b.tar.gz PrismLauncher-f032e32133023ed8396fc2b6ead7eadc2816a25b.tar.bz2 PrismLauncher-f032e32133023ed8396fc2b6ead7eadc2816a25b.zip | |
NOISSUE finalize support for new mojang version format
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 appl |
