diff --git a/api/logic/minecraft/ComponentList.cpp b/api/logic/minecraft/ComponentList.cpp index e5c373a458..c946d4b4a7 100644 --- a/api/logic/minecraft/ComponentList.cpp +++ b/api/logic/minecraft/ComponentList.cpp @@ -981,7 +981,7 @@ bool ComponentList::removeComponent_internal(ComponentPtr patch) // FIXME: we need a generic way of removing local resources, not just jar mods... auto preRemoveJarMod = [&](LibraryPtr jarMod) -> bool { - if (!jarMod->isLocal()) + if (!jarMod->isInstanceLocal()) { return true; } diff --git a/api/logic/minecraft/GradleSpecifier.h b/api/logic/minecraft/GradleSpecifier.h index 959325c6d4..e963c44297 100644 --- a/api/logic/minecraft/GradleSpecifier.h +++ b/api/logic/minecraft/GradleSpecifier.h @@ -117,7 +117,7 @@ struct GradleSpecifier } bool matchName(const GradleSpecifier & other) const { - return other.artifactId() == artifactId() && other.groupId() == groupId(); + return other.artifactId() == artifactId() && other.groupId() == groupId() && other.classifier() == classifier(); } bool operator==(const GradleSpecifier & other) const { diff --git a/api/logic/minecraft/Library.cpp b/api/logic/minecraft/Library.cpp index a56e81104c..acff662e04 100644 --- a/api/logic/minecraft/Library.cpp +++ b/api/logic/minecraft/Library.cpp @@ -11,7 +11,7 @@ void Library::getApplicableFiles(OpSys system, QStringList& jar, QStringList& native, QStringList& native32, QStringList& native64, const QString &overridePath) const { - bool local = isLocal(); + bool local = isInstanceLocal(); auto actualPath = [&](QString relPath) { QFileInfo out(FS::PathCombine(storagePrefix(), relPath)); @@ -39,7 +39,7 @@ void Library::getApplicableFiles(OpSys system, QStringList& jar, QStringList& na native += actualPath(raw_storage); } } - else + else if (!presenceOnly) { jar += actualPath(raw_storage); } @@ -54,9 +54,10 @@ QList< std::shared_ptr< NetAction > > Library::getDownloads( { QList out; bool stale = isAlwaysStale(); - bool local = isLocal(); + bool instanceLocal = isInstanceLocal(); + bool launcherLocal = isLocalBuilt(); - auto check_local_file = [&](QString storage) + auto check_instance_local_file = [&](QString storage) { QFileInfo fileinfo(storage); QString fileName = fileinfo.fileName(); @@ -70,11 +71,26 @@ QList< std::shared_ptr< NetAction > > Library::getDownloads( return true; }; + auto check_launcher_local_file = [&](QString storage) + { + QFileInfo localFileInfo("libraries/" + storage); + if(!localFileInfo.exists()) + { + failedLocalFiles.append(localFileInfo.filePath()); + return false; + } + return true; + }; + auto add_download = [&](QString storage, QString url, QString sha1) { - if(local) + if(instanceLocal) + { + return check_instance_local_file(storage); + } + else if(launcherLocal) { - return check_local_file(storage); + return check_launcher_local_file(storage); } auto entry = cache->resolveEntry("libraries", storage); if(stale) @@ -233,11 +249,16 @@ bool Library::isActive() const return result; } -bool Library::isLocal() const +bool Library::isInstanceLocal() const { return m_hint == "local"; } +bool Library::isLocalBuilt() const +{ + return localBuild; +} + bool Library::isAlwaysStale() const { return m_hint == "always-stale"; diff --git a/api/logic/minecraft/Library.h b/api/logic/minecraft/Library.h index 014f674543..2f20229161 100644 --- a/api/logic/minecraft/Library.h +++ b/api/logic/minecraft/Library.h @@ -49,6 +49,8 @@ class MULTIMC_LOGIC_EXPORT Library newlib->m_storagePrefix = base->m_storagePrefix; newlib->m_mojangDownloads = base->m_mojangDownloads; newlib->m_filename = base->m_filename; + newlib->presenceOnly = base->presenceOnly; + newlib->localBuild = base->localBuild; return newlib; } @@ -146,7 +148,15 @@ class MULTIMC_LOGIC_EXPORT Library bool isActive() const; /// Returns true if the library is contained in an instance and false if it is shared - bool isLocal() const; + bool isInstanceLocal() const; + + /// Returns true if the library cannot be downloaded (was built locally somehow) + bool isLocalBuilt() const; + + bool isLocal() const + { + return isInstanceLocal() || isLocalBuilt(); + } /// Returns true if the library is to always be checked for updates bool isAlwaysStale() const; @@ -212,6 +222,12 @@ class MULTIMC_LOGIC_EXPORT Library /// true if the library had a rules section (even empty) bool applyRules = false; + // MultiMC-specific: the artifact must be present, but is not part of the classpath + bool presenceOnly = false; + + // MultiMC-specific: the artifact must be present, but cannot be downloaded, because it was created by some other mechanism + bool localBuild = false; + /// rules associated with the library QList> m_rules; diff --git a/api/logic/minecraft/MojangDownloadInfo.h b/api/logic/minecraft/MojangDownloadInfo.h index 88f87287d9..1fa1c5bd01 100644 --- a/api/logic/minecraft/MojangDownloadInfo.h +++ b/api/logic/minecraft/MojangDownloadInfo.h @@ -36,7 +36,7 @@ struct MojangLibraryDownloadInfo { return artifact.get(); } - + return classifiers[classifier].get(); } diff --git a/api/logic/minecraft/MojangVersionFormat.cpp b/api/logic/minecraft/MojangVersionFormat.cpp index 33d3c54cb2..a8fbea656b 100644 --- a/api/logic/minecraft/MojangVersionFormat.cpp +++ b/api/logic/minecraft/MojangVersionFormat.cpp @@ -31,7 +31,7 @@ static void readDownloadInfo(MojangDownloadInfo::Ptr out, const QJsonObject &obj readString(obj, "path", out->path); // required! out->sha1 = requireString(obj, "sha1"); - out->url = requireString(obj, "url"); + out->url = ensureString(obj, "url", QString()); out->size = requireInteger(obj, "size"); } diff --git a/api/logic/minecraft/OneSixVersionFormat.cpp b/api/logic/minecraft/OneSixVersionFormat.cpp index 6f3b926ba1..63bcf002ea 100644 --- a/api/logic/minecraft/OneSixVersionFormat.cpp +++ b/api/logic/minecraft/OneSixVersionFormat.cpp @@ -21,6 +21,14 @@ LibraryPtr OneSixVersionFormat::libraryFromJson(const QJsonObject &libObj, const readString(libObj, "MMC-absoluteUrl", out->m_absoluteURL); readString(libObj, "MMC-filename", out->m_filename); readString(libObj, "MMC-displayname", out->m_displayname); + if (libObj.contains("presenceOnly")) + { + out->presenceOnly = requireBoolean(libObj, "presenceOnly"); + } + if (libObj.contains("localBuild")) + { + out->localBuild = requireBoolean(libObj, "localBuild"); + } return out; } @@ -35,6 +43,10 @@ QJsonObject OneSixVersionFormat::libraryToJson(Library *library) libRoot.insert("MMC-filename", library->m_filename); if (library->m_displayname.size()) libRoot.insert("MMC-displayname", library->m_displayname); + if (library->presenceOnly) + libRoot.insert("presenceOnly", true); + if (library->localBuild) + libRoot.insert("localBuild", true); return libRoot; }