From c4c8e99681e14e5d0e82a13cb0631107dedf96ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Mon, 17 Apr 2017 22:51:30 +0200 Subject: NOISSUE jar mods as libraries, fix for customizing net.minecraft --- api/logic/minecraft/GradleSpecifier.h | 13 +++- api/logic/minecraft/JarMod.h | 12 ---- api/logic/minecraft/Library.cpp | 49 ++++++++++++-- api/logic/minecraft/Library.h | 29 ++++++++- api/logic/minecraft/MinecraftProfile.cpp | 18 +---- api/logic/minecraft/MinecraftProfile.h | 11 +--- api/logic/minecraft/ProfilePatch.h | 1 - api/logic/minecraft/VersionFile.cpp | 7 -- api/logic/minecraft/VersionFile.h | 3 +- api/logic/minecraft/onesix/OneSixInstance.cpp | 17 ++++- .../minecraft/onesix/OneSixProfileStrategy.cpp | 24 ++++--- api/logic/minecraft/onesix/OneSixVersionFormat.cpp | 76 +++++++++++++++++----- api/logic/minecraft/onesix/OneSixVersionFormat.h | 9 ++- .../minecraft/onesix/update/LibrariesTask.cpp | 1 + 14 files changed, 186 insertions(+), 84 deletions(-) delete mode 100644 api/logic/minecraft/JarMod.h (limited to 'api/logic/minecraft') diff --git a/api/logic/minecraft/GradleSpecifier.h b/api/logic/minecraft/GradleSpecifier.h index b05553bb..f842008c 100644 --- a/api/logic/minecraft/GradleSpecifier.h +++ b/api/logic/minecraft/GradleSpecifier.h @@ -65,13 +65,22 @@ struct GradleSpecifier filename += "." + m_extension; return filename; } - QString toPath() const + QString toPath(const QString & filenameOverride = QString()) const { if(!m_valid) return "INVALID"; + QString filename; + if(filenameOverride.isEmpty()) + { + filename = getFileName(); + } + else + { + filename = filenameOverride; + } QString path = m_groupId; path.replace('.', '/'); - path += '/' + m_artifactId + '/' + m_version + '/' + getFileName(); + path += '/' + m_artifactId + '/' + m_version + '/' + filename; return path; } inline bool valid() const diff --git a/api/logic/minecraft/JarMod.h b/api/logic/minecraft/JarMod.h deleted file mode 100644 index 42d05da9..00000000 --- a/api/logic/minecraft/JarMod.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include -#include -#include -class Jarmod; -typedef std::shared_ptr JarmodPtr; -class Jarmod -{ -public: /* data */ - QString name; - QString originalName; -}; diff --git a/api/logic/minecraft/Library.cpp b/api/logic/minecraft/Library.cpp index a3b5f01c..22e1bd33 100644 --- a/api/logic/minecraft/Library.cpp +++ b/api/logic/minecraft/Library.cpp @@ -11,11 +11,11 @@ void Library::getApplicableFiles(OpSys system, QStringList& jar, QStringList& native, QStringList& native32, QStringList& native64, const QString &overridePath) const { - bool isLocal = (hint() == "local"); + bool local = isLocal(); auto actualPath = [&](QString relPath) { QFileInfo out(FS::PathCombine(storagePrefix(), relPath)); - if(isLocal && !overridePath.isEmpty()) + if(local && !overridePath.isEmpty()) { QString fileName = out.fileName(); auto fullPath = FS::PathCombine(overridePath, fileName); @@ -56,7 +56,7 @@ QList< std::shared_ptr< NetAction > > Library::getDownloads(OpSys system, class { QList out; bool isAlwaysStale = (hint() == "always-stale"); - bool isLocal = (hint() == "local"); + bool local = isLocal(); bool isForge = (hint() == "forge-pack-xz"); auto add_download = [&](QString storage, QString url, QString sha1 = QString()) @@ -68,7 +68,7 @@ QList< std::shared_ptr< NetAction > > Library::getDownloads(OpSys system, class } if (!entry->isStale()) return true; - if(isLocal) + if(local) { if(!overridePath.isEmpty()) { @@ -228,6 +228,11 @@ bool Library::isActive() const return result; } +bool Library::isLocal() const +{ + return m_hint == "local"; +} + void Library::setStoragePrefix(QString prefix) { m_storagePrefix = prefix; @@ -247,12 +252,44 @@ QString Library::storagePrefix() const return m_storagePrefix; } +QString Library::filename(OpSys system) const +{ + if(!m_filename.isEmpty()) + { + return m_filename; + } + // non-native? use only the gradle specifier + if (!isNative()) + { + return m_name.getFileName(); + } + + // otherwise native, override classifiers. Mojang HACK! + GradleSpecifier nativeSpec = m_name; + if (m_nativeClassifiers.contains(system)) + { + nativeSpec.setClassifier(m_nativeClassifiers[system]); + } + else + { + nativeSpec.setClassifier("INVALID"); + } + return nativeSpec.getFileName(); +} + +QString Library::displayName(OpSys system) const +{ + if(!m_displayname.isEmpty()) + return m_displayname; + return filename(system); +} + QString Library::storageSuffix(OpSys system) const { // non-native? use only the gradle specifier if (!isNative()) { - return m_name.toPath(); + return m_name.toPath(m_filename); } // otherwise native, override classifiers. Mojang HACK! @@ -265,5 +302,5 @@ QString Library::storageSuffix(OpSys system) const { nativeSpec.setClassifier("INVALID"); } - return nativeSpec.toPath(); + return nativeSpec.toPath(m_filename); } diff --git a/api/logic/minecraft/Library.h b/api/logic/minecraft/Library.h index 6369c537..9577de33 100644 --- a/api/logic/minecraft/Library.h +++ b/api/logic/minecraft/Library.h @@ -48,6 +48,7 @@ public: newlib->m_rules = base->m_rules; newlib->m_storagePrefix = base->m_storagePrefix; newlib->m_mojangDownloads = base->m_mojangDownloads; + newlib->m_filename = base->m_filename; return newlib; } @@ -108,6 +109,23 @@ public: /* methods */ m_absoluteURL = absolute_url; } + void setFilename(const QString &filename) + { + m_filename = filename; + } + + /// Get the file name of the library + QString filename(OpSys system) const; + + // DEPRECATED: set a display name, used by jar mods only + void setDisplayName(const QString & displayName) + { + m_displayname = displayName; + } + + /// Get the file name of the library + QString displayName(OpSys system) const; + void setMojangDownloadInfo(MojangLibraryDownloadInfo::Ptr info) { m_mojangDownloads = info; @@ -127,6 +145,9 @@ public: /* methods */ /// Returns true if the library should be loaded (or extracted, in case of natives) bool isActive() const; + /// Returns true if the library is contained in an instance and false if it is shared + bool isLocal() const; + // Get a list of downloads for this library QList getDownloads(OpSys system, class HttpMetaCache * cache, QStringList & failedFiles, const QString & overridePath) const; @@ -138,7 +159,7 @@ private: /* methods */ /// Get the prefix - root of the storage to be used QString storagePrefix() const; - /// Get the relative path where the library should be saved + /// Get the relative file path where the library should be saved QString storageSuffix(OpSys system) const; QString hint() const @@ -156,6 +177,12 @@ protected: /* data */ /// DEPRECATED: MultiMC-specific absolute URL. takes precedence over the implicit maven repo URL, if defined QString m_absoluteURL; + /// MultiMC extension - filename override + QString m_filename; + + /// DEPRECATED MultiMC extension - display name + QString m_displayname; + /** * MultiMC-specific type hint - modifies how the library is treated */ diff --git a/api/logic/minecraft/MinecraftProfile.cpp b/api/logic/minecraft/MinecraftProfile.cpp index efe4651b..a82d892f 100644 --- a/api/logic/minecraft/MinecraftProfile.cpp +++ b/api/logic/minecraft/MinecraftProfile.cpp @@ -79,7 +79,7 @@ void MinecraftProfile::clear() m_libraries.clear(); m_traits.clear(); m_jarMods.clear(); - mojangDownloads.clear(); + m_mainJar.reset(); m_problemSeverity = ProblemSeverity::None; } @@ -437,18 +437,6 @@ 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& traits) { this->m_traits.unite(traits); @@ -464,7 +452,7 @@ void MinecraftProfile::applyTweakers(const QStringList& tweakers) } } -void MinecraftProfile::applyJarMods(const QList& jarMods) +void MinecraftProfile::applyJarMods(const QList& jarMods) { this->m_jarMods.append(jarMods); } @@ -593,7 +581,7 @@ QString MinecraftProfile::getMinecraftArguments() const return m_minecraftArguments; } -const QList & MinecraftProfile::getJarMods() const +const QList & MinecraftProfile::getJarMods() const { return m_jarMods; } diff --git a/api/logic/minecraft/MinecraftProfile.h b/api/logic/minecraft/MinecraftProfile.h index 93a02197..6e72afa1 100644 --- a/api/logic/minecraft/MinecraftProfile.h +++ b/api/logic/minecraft/MinecraftProfile.h @@ -23,7 +23,6 @@ #include "Library.h" #include "ProfilePatch.h" -#include "JarMod.h" #include "BaseVersion.h" #include "MojangDownloadInfo.h" @@ -99,11 +98,10 @@ public: /* application of profile variables from patches */ void applyMinecraftAssets(MojangAssetIndexInfo::Ptr assets); void applyTraits(const QSet &traits); void applyTweakers(const QStringList &tweakers); - void applyJarMods(const QList &jarMods); + void applyJarMods(const QList &jarMods); void applyLibrary(LibraryPtr library); void applyMainJar(LibraryPtr jar); void applyProblemSeverity(ProblemSeverity severity); - void applyMojangDownload(const QString & key, MojangDownloadInfo::Ptr download); public: /* getters for profile variables */ QString getMinecraftVersion() const; @@ -114,7 +112,7 @@ public: /* getters for profile variables */ QString getMinecraftArguments() const; const QSet & getTraits() const; const QStringList & getTweakers() const; - const QList & getJarMods() const; + const QList & getJarMods() const; const QList & getLibraries() const; const QList & getNativeLibraries() const; const LibraryPtr getMainJar() const; @@ -149,9 +147,6 @@ 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 > mojangDownloads; - /** * arguments that should be used for launching minecraft * @@ -182,7 +177,7 @@ private: /* data */ QSet m_traits; /// A list of jar mods. version files can add those. - QList m_jarMods; + QList m_jarMods; ProblemSeverity m_problemSeverity = ProblemSeverity::None; diff --git a/api/logic/minecraft/ProfilePatch.h b/api/logic/minecraft/ProfilePatch.h index fb6b2f05..4e72f9cf 100644 --- a/api/logic/minecraft/ProfilePatch.h +++ b/api/logic/minecraft/ProfilePatch.h @@ -4,7 +4,6 @@ #include #include #include -#include "JarMod.h" #include "ProblemProvider.h" class MinecraftProfile; diff --git a/api/logic/minecraft/VersionFile.cpp b/api/logic/minecraft/VersionFile.cpp index 3e1461ed..b6e2ab37 100644 --- a/api/logic/minecraft/VersionFile.cpp +++ b/api/logic/minecraft/VersionFile.cpp @@ -6,7 +6,6 @@ #include "minecraft/VersionFile.h" #include "minecraft/Library.h" #include "minecraft/MinecraftProfile.h" -#include "minecraft/JarMod.h" #include "ParseUtils.h" #include "VersionBuildError.h" @@ -43,12 +42,6 @@ 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/api/logic/minecraft/VersionFile.h b/api/logic/minecraft/VersionFile.h index 830e2ca0..b673811c 100644 --- a/api/logic/minecraft/VersionFile.h +++ b/api/logic/minecraft/VersionFile.h @@ -10,7 +10,6 @@ #include "minecraft/Rule.h" #include "ProblemProvider.h" #include "Library.h" -#include "JarMod.h" class MinecraftProfile; class VersionFile; @@ -84,7 +83,7 @@ public: /* data */ QSet traits; /// MultiMC: list of jar mods added to this version - QList jarMods; + QList jarMods; public: // Mojang: DEPRECATED list of 'downloads' - client jar, server jar, windows server exe, maybe more. diff --git a/api/logic/minecraft/onesix/OneSixInstance.cpp b/api/logic/minecraft/onesix/OneSixInstance.cpp index 0061be08..7e4e97b7 100644 --- a/api/logic/minecraft/onesix/OneSixInstance.cpp +++ b/api/logic/minecraft/onesix/OneSixInstance.cpp @@ -314,7 +314,16 @@ QStringList OneSixInstance::verboseDescription(AuthSessionPtr session) out << "Jar Mods:"; for(auto & jarmod: jarMods) { - out << " " + jarmod->originalName + " (" + jarmod->name + ")"; + auto displayname = jarmod->displayName(currentSystem); + auto realname = jarmod->filename(currentSystem); + if(displayname != realname) + { + out << " " + displayname + " (" + realname + ")"; + } + else + { + out << " " + realname; + } } out << ""; } @@ -521,8 +530,10 @@ QList< Mod > OneSixInstance::getJarMods() const QList mods; for (auto jarmod : m_profile->getJarMods()) { - QString filePath = jarmodsPath().absoluteFilePath(jarmod->name); - mods.push_back(Mod(QFileInfo(filePath))); + QStringList jar, temp1, temp2, temp3; + jarmod->getApplicableFiles(currentSystem, jar, temp1, temp2, temp3, jarmodsPath().absolutePath()); + // QString filePath = jarmodsPath().absoluteFilePath(jarmod->filename(currentSystem)); + mods.push_back(Mod(QFileInfo(jar[0]))); } return mods; } diff --git a/api/logic/minecraft/onesix/OneSixProfileStrategy.cpp b/api/logic/minecraft/onesix/OneSixProfileStrategy.cpp index d3e137c7..b4be3356 100644 --- a/api/logic/minecraft/onesix/OneSixProfileStrategy.cpp +++ b/api/logic/minecraft/onesix/OneSixProfileStrategy.cpp @@ -248,16 +248,22 @@ bool OneSixProfileStrategy::removePatch(ProfilePatchPtr patch) m_instance->setComponentVersion(patch->getID(), QString()); } - auto preRemoveJarMod = [&](JarmodPtr jarMod) -> bool + // FIXME: we need a generic way of removing local resources, not just jar mods... + auto preRemoveJarMod = [&](LibraryPtr jarMod) -> bool { - QString fullpath = FS::PathCombine(m_instance->jarModsDir(), jarMod->name); - QFileInfo finfo (fullpath); + if (!jarMod->isLocal()) + { + return true; + } + QStringList jar, temp1, temp2, temp3; + jarMod->getApplicableFiles(currentSystem, jar, temp1, temp2, temp3, m_instance->jarmodsPath().absolutePath()); + QFileInfo finfo (jar[0]); if(finfo.exists()) { - QFile jarModFile(fullpath); + QFile jarModFile(jar[0]); if(!jarModFile.remove()) { - qCritical() << "File" << fullpath << "could not be removed because:" << jarModFile.errorString(); + qCritical() << "File" << jar[0] << "could not be removed because:" << jarModFile.errorString(); return false; } return true; @@ -381,9 +387,11 @@ bool OneSixProfileStrategy::installJarMods(QStringList filepaths) } auto f = std::make_shared(); - auto jarMod = std::make_shared(); - jarMod->name = target_filename; - jarMod->originalName = sourceInfo.completeBaseName(); + auto jarMod = std::make_shared(); + jarMod->setRawName(GradleSpecifier("org.multimc.jarmods:" + id + ":1")); + jarMod->setFilename(target_filename); + jarMod->setDisplayName(sourceInfo.completeBaseName()); + jarMod->setHint("local"); f->jarMods.append(jarMod); f->name = target_name; f->uid = target_id; diff --git a/api/logic/minecraft/onesix/OneSixVersionFormat.cpp b/api/logic/minecraft/onesix/OneSixVersionFormat.cpp index c404e96f..da55d91b 100644 --- a/api/logic/minecraft/onesix/OneSixVersionFormat.cpp +++ b/api/logic/minecraft/onesix/OneSixVersionFormat.cpp @@ -20,6 +20,8 @@ LibraryPtr OneSixVersionFormat::libraryFromJson(const QJsonObject &libObj, const readString(libObj, "MMC-hint", out->m_hint); readString(libObj, "MMC-absulute_url", out->m_absoluteURL); readString(libObj, "MMC-absoluteUrl", out->m_absoluteURL); + readString(libObj, "MMC-filename", out->m_filename); + readString(libObj, "MMC-displayname", out->m_displayname); return out; } @@ -30,6 +32,10 @@ QJsonObject OneSixVersionFormat::libraryToJson(Library *library) libRoot.insert("MMC-absoluteUrl", library->m_absoluteURL); if (library->m_hint.size()) libRoot.insert("MMC-hint", library->m_hint); + if (library->m_filename.size()) + libRoot.insert("MMC-filename", library->m_filename); + if (library->m_displayname.size()) + libRoot.insert("MMC-displayname", library->m_displayname); return libRoot; } @@ -96,13 +102,25 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc } } - if (root.contains("+jarMods")) + + if (root.contains("jarMods")) + { + for (auto libVal : requireArray(root.value("jarMods"))) + { + QJsonObject libObj = requireObject(libVal); + // parse the jarmod + auto lib = OneSixVersionFormat::jarModFromJson(libObj, filename); + // and add to jar mods + out->jarMods.append(lib); + } + } + else if (root.contains("+jarMods")) // DEPRECATED: old style '+jarMods' are only here for backwards compatibility { for (auto libVal : requireArray(root.value("+jarMods"))) { QJsonObject libObj = requireObject(libVal); // parse the jarmod - auto lib = OneSixVersionFormat::jarModFromJson(libObj, filename, out->name); + auto lib = OneSixVersionFormat::plusJarModFromJson(libObj, filename, out->name); // and add to jar mods out->jarMods.append(lib); } @@ -197,13 +215,16 @@ QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch writeString(root, "name", patch->name); writeString(root, "uid", patch->uid); - writeString(root, "fileId", patch->uid); writeString(root, "version", patch->version); writeString(root, "mcVersion", patch->dependsOnMinecraftVersion); MojangVersionFormat::writeVersionProperties(patch.get(), root); + if(patch->mainJar) + { + root.insert("mainJar", libraryToJson(patch->mainJar.get())); + } writeString(root, "appletClass", patch->appletClass); writeStringList(root, "+tweakers", patch->addTweakers); writeStringList(root, "+traits", patch->traits.toList()); @@ -214,7 +235,7 @@ QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch { array.append(OneSixVersionFormat::libraryToJson(value.get())); } - root.insert("+libraries", array); + root.insert("libraries", array); } if (!patch->jarMods.isEmpty()) { @@ -223,7 +244,7 @@ QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch { array.append(OneSixVersionFormat::jarModtoJson(value.get())); } - root.insert("+jarMods", array); + root.insert("jarMods", array); } // write the contents to a json document. { @@ -233,32 +254,55 @@ QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch } } -JarmodPtr OneSixVersionFormat::jarModFromJson(const QJsonObject &libObj, const QString &filename, const QString &originalName) +LibraryPtr OneSixVersionFormat::plusJarModFromJson(const QJsonObject &libObj, const QString &filename, const QString &originalName) { - JarmodPtr out(new Jarmod()); + LibraryPtr out(new Library()); if (!libObj.contains("name")) { throw JSONValidationError(filename + "contains a jarmod that doesn't have a 'name' field"); } - out->name = libObj.value("name").toString(); - out->originalName = libObj.value("originalName").toString(); - if(out->originalName.isEmpty()) + + // just make up something unique on the spot for the library name. + auto uuid = QUuid::createUuid(); + QString id = uuid.toString().remove('{').remove('}'); + + + // filename override is the old name + out->setFilename(libObj.value("name").toString()); + + // it needs to be local, it is stored in the instance jarmods folder + out->setHint("local"); + + // read the original name if present - some versions did not set it + // it is the original jar mod filename before it got renamed at the point of addition + auto displayName = libObj.value("originalName").toString(); + if(displayName.isEmpty()) { auto fixed = originalName; fixed.remove(" (jar mod)"); - out->originalName = originalName; + out->setDisplayName(fixed); + } + else + { + out->setDisplayName(displayName); } return out; } -QJsonObject OneSixVersionFormat::jarModtoJson(Jarmod *jarmod) +LibraryPtr OneSixVersionFormat::jarModFromJson(const QJsonObject& libObj, const QString& filename) +{ + auto lib = libraryFromJson(libObj, filename); + return lib; +} + + +QJsonObject OneSixVersionFormat::jarModtoJson(Library *jarmod) { - QJsonObject out; - writeString(out, "name", jarmod->name); - if(!jarmod->originalName.isEmpty()) + QJsonObject out = libraryToJson(jarmod); + if(!jarmod->m_displayname.isEmpty()) { - writeString(out, "originalName", jarmod->originalName); + writeString(out, "originalName", jarmod->m_displayname); } return out; } diff --git a/api/logic/minecraft/onesix/OneSixVersionFormat.h b/api/logic/minecraft/onesix/OneSixVersionFormat.h index 5696e79e..0a29a202 100644 --- a/api/logic/minecraft/onesix/OneSixVersionFormat.h +++ b/api/logic/minecraft/onesix/OneSixVersionFormat.h @@ -16,7 +16,10 @@ public: static LibraryPtr libraryFromJson(const QJsonObject &libObj, const QString &filename); static QJsonObject libraryToJson(Library *library); - // jar mods - static JarmodPtr jarModFromJson(const QJsonObject &libObj, const QString &filename, const QString &originalName); - static QJsonObject jarModtoJson(Jarmod * jarmod); + // DEPRECATED: old 'plus' jar mods generated by the application + static LibraryPtr plusJarModFromJson(const QJsonObject &libObj, const QString &filename, const QString &originalName); + + // new jar mods derived from libraries + static LibraryPtr jarModFromJson(const QJsonObject &libObj, const QString &filename); + static QJsonObject jarModtoJson(Library * jarmod); }; diff --git a/api/logic/minecraft/onesix/update/LibrariesTask.cpp b/api/logic/minecraft/onesix/update/LibrariesTask.cpp index 1b7e71d3..2cd41ded 100644 --- a/api/logic/minecraft/onesix/update/LibrariesTask.cpp +++ b/api/logic/minecraft/onesix/update/LibrariesTask.cpp @@ -50,6 +50,7 @@ void LibrariesTask::executeTask() }; createJobs(profile->getLibraries()); createJobs(profile->getNativeLibraries()); + createJobs(profile->getJarMods()); createJob(profile->getMainJar()); // FIXME: this is never filled!!!! -- cgit v1.2.3