diff options
| author | Petr Mrázek <peterix@gmail.com> | 2014-05-05 00:10:59 +0200 |
|---|---|---|
| committer | Petr Mrázek <peterix@gmail.com> | 2014-06-09 01:38:29 +0200 |
| commit | 4c3bd416c65ec887209fa06b0a5634099b77f322 (patch) | |
| tree | f656031d147aba8f8dd621de2bd452ea1bfd86b4 | |
| parent | aade36860c373268857ca821c14a13f38c880b1a (diff) | |
| download | PrismLauncher-4c3bd416c65ec887209fa06b0a5634099b77f322.tar.gz PrismLauncher-4c3bd416c65ec887209fa06b0a5634099b77f322.tar.bz2 PrismLauncher-4c3bd416c65ec887209fa06b0a5634099b77f322.zip | |
Much change, very jarmod.
46 files changed, 3735 insertions, 142 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 4617020a..4309c55f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -374,6 +374,10 @@ SET(MULTIMC_SOURCES logic/Mod.cpp logic/ModList.h logic/ModList.cpp + + # sets and maps for deciding based on versions + logic/VersionFilterData.h + logic/VersionFilterData.cpp # Basic instance launcher for starting from terminal logic/InstanceLauncher.h @@ -545,8 +549,6 @@ SET(MULTIMC_SOURCES logic/tools/JVisualVM.cpp # Forge and all things forge related - logic/forge/ForgeData.h - logic/forge/ForgeData.cpp logic/forge/ForgeVersion.h logic/forge/ForgeVersion.cpp logic/forge/ForgeVersionList.h @@ -566,6 +568,10 @@ SET(MULTIMC_SOURCES logic/liteloader/LiteLoaderInstaller.cpp logic/liteloader/LiteLoaderVersionList.h logic/liteloader/LiteLoaderVersionList.cpp + + # MultiMC URN resolver + logic/URNResolver.cpp + logic/URNResolver.h ) diff --git a/MultiMC.cpp b/MultiMC.cpp index 28fe8e26..6b5545c1 100644 --- a/MultiMC.cpp +++ b/MultiMC.cpp @@ -38,6 +38,8 @@ #include "logic/tools/JVisualVM.h" #include "logic/tools/MCEditTool.h" +#include "logic/URNResolver.h" + #include "pathutils.h" #include "cmdutils.h" #include <inisettingsobject.h> @@ -644,6 +646,16 @@ std::shared_ptr<JavaVersionList> MultiMC::javalist() return m_javalist; } +std::shared_ptr<URNResolver> MultiMC::resolver() +{ + if (!m_resolver) + { + m_resolver.reset(new URNResolver()); + } + return m_resolver; +} + + void MultiMC::installUpdates(const QString updateFilesDir, UpdateFlags flags) { // if we are going to update on exit, save the params now @@ -23,6 +23,7 @@ class NewsChecker; class StatusChecker; class BaseProfilerFactory; class BaseDetachedToolFactory; +class URNResolver; #if defined(MMC) #undef MMC @@ -128,6 +129,8 @@ public: std::shared_ptr<JavaVersionList> javalist(); + std::shared_ptr<URNResolver> resolver(); + QMap<QString, std::shared_ptr<BaseProfilerFactory>> profilers() { return m_profilers; @@ -214,8 +217,11 @@ private: std::shared_ptr<LiteLoaderVersionList> m_liteloaderlist; std::shared_ptr<MinecraftVersionList> m_minecraftlist; std::shared_ptr<JavaVersionList> m_javalist; + std::shared_ptr<URNResolver> m_resolver; + QMap<QString, std::shared_ptr<BaseProfilerFactory>> m_profilers; QMap<QString, std::shared_ptr<BaseDetachedToolFactory>> m_tools; + QsLogging::DestinationPtr m_fileDestination; QsLogging::DestinationPtr m_debugDestination; diff --git a/depends/launcher/org/multimc/onesix/OneSixLauncher.java b/depends/launcher/org/multimc/onesix/OneSixLauncher.java index 28f8e6ee..a908f6f3 100644 --- a/depends/launcher/org/multimc/onesix/OneSixLauncher.java +++ b/depends/launcher/org/multimc/onesix/OneSixLauncher.java @@ -38,6 +38,7 @@ public class OneSixLauncher implements Launcher List<String> extlibs; List<String> mcparams; List<String> mods; + List<String> traits; String mainClass; String natives; final String windowTitle; @@ -49,6 +50,7 @@ public class OneSixLauncher implements Launcher mcparams = params.all("param"); mainClass = params.first("mainClass"); mods = params.allSafe("mods", new ArrayList<String>()); + traits = params.allSafe("traits", new ArrayList<String>()); natives = params.first("natives"); windowTitle = params.first("windowTitle"); diff --git a/gui/dialogs/InstanceEditDialog.cpp b/gui/dialogs/InstanceEditDialog.cpp index fe2d1b03..a74f3dcb 100644 --- a/gui/dialogs/InstanceEditDialog.cpp +++ b/gui/dialogs/InstanceEditDialog.cpp @@ -262,45 +262,6 @@ void InstanceEditDialog::on_moveLibraryDownBtn_clicked() } } -// FIXME: use this for legacy forge... or abstract away. -/* -void LegacyModEditDialog::on_addForgeBtn_clicked() -{ - VersionSelectDialog vselect(MMC->forgelist().get(), tr("Select Forge version"), this); - vselect.setFilter(1, m_inst->intendedVersionId()); - if (vselect.exec() && vselect.selectedVersion()) - { - ForgeVersionPtr forge = - std::dynamic_pointer_cast<ForgeVersion>(vselect.selectedVersion()); - if (!forge) - return; - auto entry = MMC->metacache()->resolveEntry("minecraftforge", forge->filename); - if (entry->stale) - { - NetJob *fjob = new NetJob("Forge download"); - fjob->addNetAction(CacheDownload::make(forge->universal_url, entry)); - ProgressDialog dlg(this); - dlg.exec(fjob); - if (dlg.result() == QDialog::Accepted) - { - m_jarmods->stopWatching(); - m_jarmods->installMod(QFileInfo(entry->getFullPath())); - m_jarmods->startWatching(); - } - else - { - // failed to download forge :/ - } - } - else - { - m_jarmods->stopWatching(); - m_jarmods->installMod(QFileInfo(entry->getFullPath())); - m_jarmods->startWatching(); - } - } -}*/ - void InstanceEditDialog::on_changeMCVersionBtn_clicked() { VersionSelectDialog vselect(m_inst->versionList().get(), tr("Change Minecraft version"), this); @@ -343,24 +304,6 @@ void InstanceEditDialog::on_changeMCVersionBtn_clicked() tDialog.exec(updateTask.get()); } -/* -void MainWindow::on_actionChangeInstLWJGLVersion_triggered() -{ - if (!m_selectedInstance) - return; - - LWJGLSelectDialog lselect(this); - lselect.exec(); - if (lselect.result() == QDialog::Accepted) - { - auto ptr = std::dynamic_pointer_cast<LegacyInstance>(m_selectedInstance); - if(ptr) - ptr->setLWJGLVersion(lselect.selectedVersion()); - } -} -*/ - - void InstanceEditDialog::on_forgeBtn_clicked() { // FIXME: use actual model, not reloading. Move logic to model. diff --git a/logic/BaseInstance.h b/logic/BaseInstance.h index 16791592..41ceda39 100644 --- a/logic/BaseInstance.h +++ b/logic/BaseInstance.h @@ -89,7 +89,7 @@ public: void setGroupInitial(QString val); void setGroupPost(QString val); - QStringList extraArguments() const; + virtual QStringList extraArguments() const; virtual QString intendedVersionId() const = 0; virtual bool setIntendedVersionId(QString version) = 0; diff --git a/logic/LegacyUpdate.cpp b/logic/LegacyUpdate.cpp index 6816df40..aea88c95 100644 --- a/logic/LegacyUpdate.cpp +++ b/logic/LegacyUpdate.cpp @@ -64,7 +64,7 @@ void LegacyUpdate::fmllibsStart() bool forge_present = false; QString version = inst->intendedVersionId(); - auto & fmlLibsMapping = g_forgeData.fmlLibsMapping; + auto & fmlLibsMapping = g_VersionFilterData.fmlLibsMapping; if (!fmlLibsMapping.contains(version)) { lwjglStart(); diff --git a/logic/LegacyUpdate.h b/logic/LegacyUpdate.h index 1550ec34..140ee1e3 100644 --- a/logic/LegacyUpdate.h +++ b/logic/LegacyUpdate.h @@ -21,7 +21,7 @@ #include "logic/net/NetJob.h" #include "logic/tasks/Task.h" -#include "logic/forge/ForgeData.h" +#include "logic/VersionFilterData.h" class MinecraftVersion; class BaseInstance; diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index dc452188..9057a6e3 100644 --- a/logic/OneSixInstance.cpp +++ b/logic/OneSixInstance.cpp @@ -29,7 +29,8 @@ #include "gui/dialogs/InstanceEditDialog.h" #include <MMCError.h> -OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *settings, QObject *parent) +OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *settings, + QObject *parent) : BaseInstance(new OneSixInstancePrivate(), rootDir, settings, parent) { I_D(OneSixInstance); @@ -47,7 +48,7 @@ void OneSixInstance::init() { reloadVersion(); } - catch(MMCError & e) + catch (MMCError &e) { // QLOG_ERROR() << "Caught exception on instance init: " << e.cause(); } @@ -125,7 +126,7 @@ QDir OneSixInstance::reconstructAssets(std::shared_ptr<VersionFinal> version) QString original_path = PathCombine(PathCombine(objectDir.path(), tlk), asset_object.hash); QFile original(original_path); - if(!original.exists()) + if (!original.exists()) continue; if (!target.exists()) { @@ -137,7 +138,7 @@ QDir OneSixInstance::reconstructAssets(std::shared_ptr<VersionFinal> version) bool couldCopy = original.copy(target_path); QLOG_DEBUG() << " Copying" << original_path << "to" << target_path - << QString::number(couldCopy); // << original.errorString(); + << QString::number(couldCopy); // << original.errorString(); } } @@ -205,8 +206,20 @@ bool OneSixInstance::prepareForLaunch(AuthSessionPtr account, QString &launchScr { launchScript += "cp " + librariesPath().absoluteFilePath(lib->storagePath()) + "\n"; } - QString targetstr = version->id + "/" + version->id + ".jar"; - launchScript += "cp " + versionsPath().absoluteFilePath(targetstr) + "\n"; + QString minecraftjarpath; + if (version->hasJarMods()) + { + for (auto jarmod : version->jarMods) + { + launchScript += "cp " + jarmodsPath().absoluteFilePath(jarmod->name) + "\n"; + } + minecraftjarpath = version->id + "/" + version->id + "-stripped.jar"; + } + else + { + minecraftjarpath = version->id + "/" + version->id + ".jar"; + } + launchScript += "cp " + versionsPath().absoluteFilePath(minecraftjarpath) + "\n"; } launchScript += "mainClass " + version->mainClass + "\n"; @@ -231,12 +244,16 @@ bool OneSixInstance::prepareForLaunch(AuthSessionPtr account, QString &launchScr } QDir natives_dir(PathCombine(instanceRoot(), "natives/")); launchScript += "windowTitle " + windowTitle() + "\n"; - for(auto native: version->getActiveNativeLibs()) + for (auto native : version->getActiveNativeLibs()) { QFileInfo finfo(PathCombine("libraries", native->storagePath())); launchScript += "ext " + finfo.absoluteFilePath() + "\n"; } launchScript += "natives " + natives_dir.absolutePath() + "\n"; + for (auto trait : version->traits) + { + launchScript += "trait " + trait + "\n"; + } launchScript += "launcher onesix\n"; return true; } @@ -319,7 +336,7 @@ bool OneSixInstance::versionIsCustom() { I_D(const OneSixInstance); auto ver = d->version; - if(ver) + if (ver) { return !ver->isVanilla(); } @@ -330,7 +347,7 @@ bool OneSixInstance::versionIsFTBPack() { I_D(const OneSixInstance); auto ver = d->version; - if(ver) + if (ver) { return ver->hasFtbPack(); } @@ -352,11 +369,11 @@ void OneSixInstance::reloadVersion() d->m_flags.remove(VersionBrokenFlag); emit versionReloaded(); } - catch(MMCError & error) + catch (MMCError &error) { d->version->clear(); d->m_flags.insert(VersionBrokenFlag); - //TODO: rethrow to show some error message(s)? + // TODO: rethrow to show some error message(s)? emit versionReloaded(); throw; } @@ -409,8 +426,8 @@ QString OneSixInstance::getStatusbarDescription() { traits.append(tr("broken")); } - - if(traits.size()) + + if (traits.size()) { return tr("Minecraft %1 (%2)").arg(intendedVersionId()).arg(traits.join(", ")); } @@ -424,6 +441,12 @@ QDir OneSixInstance::librariesPath() const { return QDir::current().absoluteFilePath("libraries"); } + +QDir OneSixInstance::jarmodsPath() const +{ + return QDir(jarModsDir()); +} + QDir OneSixInstance::versionsPath() const { return QDir::current().absoluteFilePath("versions"); @@ -441,7 +464,7 @@ bool OneSixInstance::providesVersionFile() const bool OneSixInstance::reload() { - if(BaseInstance::reload()) + if (BaseInstance::reload()) { try { @@ -480,3 +503,22 @@ QString OneSixInstance::jarModsDir() const { return PathCombine(instanceRoot(), "jarmods"); } + +QString OneSixInstance::libDir() const +{ + return PathCombine(minecraftRoot(), "lib"); +} + +QStringList OneSixInstance::extraArguments() const +{ + auto list = BaseInstance::extraArguments(); + auto version = getFullVersion(); + if (!version) + return list; + if (version->hasJarMods()) + { + list.append({"-Dfml.ignoreInvalidMinecraftCertificates=true", + "-Dfml.ignorePatchDiscrepancies=true"}); + } + return list; +} diff --git a/logic/OneSixInstance.h b/logic/OneSixInstance.h index b26ff752..80b197c4 100644 --- a/logic/OneSixInstance.h +++ b/logic/OneSixInstance.h @@ -40,6 +40,7 @@ public: QString resourcePacksDir() const; QString loaderModsDir() const; QString coreModsDir() const; + QString libDir() const; virtual QString instanceConfigFolder() const override; virtual std::shared_ptr<Task> doUpdate() override; @@ -82,13 +83,15 @@ public: virtual bool menuActionEnabled(QString action_name) const override; virtual QString getStatusbarDescription() override; + virtual QDir jarmodsPath() const; virtual QDir librariesPath() const; virtual QDir versionsPath() const; virtual QStringList externalPatches() const; virtual bool providesVersionFile() const; bool reload() override; - + virtual QStringList extraArguments() const override; + signals: void versionReloaded(); diff --git a/logic/OneSixUpdate.cpp b/logic/OneSixUpdate.cpp index da2fd29c..230ef9a9 100644 --- a/logic/OneSixUpdate.cpp +++ b/logic/OneSixUpdate.cpp @@ -259,7 +259,7 @@ void OneSixUpdate::jarlibStart() auto metacache = MMC->metacache(); auto entry = metacache->resolveEntry("versions", localPath); job->addNetAction(CacheDownload::make(QUrl(urlstr), entry)); - + jarHashOnEntry = entry->md5sum; jarlibDownloadJob.reset(job); } @@ -341,7 +341,36 @@ void OneSixUpdate::jarlibStart() void OneSixUpdate::jarlibFinished() { - assetIndexStart(); + OneSixInstance *inst = (OneSixInstance *)m_inst; + std::shared_ptr<VersionFinal> version = inst->getFullVersion(); + + // create stripped jar, if needed + if(version->hasJarMods()) + { + //FIXME: good candidate for moving elsewhere (jar location resolving/version caching). + QString version_id = version->id; + QString localPath = version_id + "/" + version_id + ".jar"; + QString strippedPath = version_id + "/" + version_id + "-stripped.jar"; + auto metacache = MMC->metacache(); + auto entry = metacache->resolveEntry("versions", localPath); + auto entryStripped = metacache->resolveEntry("versions", strippedPath); + + QString fullJarPath = entry->getFullPath(); + QString fullStrippedJarPath = entryStripped->getFullPath(); + + if(entry->md5sum != jarHashOnEntry || !QFileInfo::exists(fullStrippedJarPath)) + { + stripJar(fullJarPath, fullStrippedJarPath); + } + } + if(version->traits.contains("legacyFML")) + { + fmllibsStart(); + } + else + { + assetIndexStart(); + } } void OneSixUpdate::jarlibFailed() @@ -350,3 +379,184 @@ void OneSixUpdate::jarlibFailed() QString failed_all = failed.join("\n"); emitFailed(tr("Failed to download the following files:\n%1\n\nPlease try again.").arg(failed_all)); } + +void OneSixUpdate::stripJar(QString origPath, QString newPath) +{ + QFileInfo runnableJar(newPath); + if (runnableJar.exists() && !QFile::remove(runnableJar.filePath())) + { + emitFailed("Failed to delete old minecraft.jar"); + return; + } + + // TaskStep(); // STEP 1 + setStatus(tr("Creating stripped jar: Opening minecraft.jar ...")); + + QuaZip zipOut(runnableJar.filePath()); + if (!zipOut.open(QuaZip::mdCreate)) + { + QFile::remove(runnableJar.filePath()); + emitFailed("Failed to open the minecraft.jar for stripping"); + return; + } + // Modify the jar + setStatus(tr("Creating stripped jar: Adding files...")); + if (!MergeZipFiles(&zipOut, origPath)) + { + zipOut.close(); + QFile::remove(runnableJar.filePath()); + emitFailed("Failed to add " + origPath + " to the jar."); + return; + } +} + +bool OneSixUpdate::MergeZipFiles(QuaZip *into, QString from) +{ + setStatus(tr("Installing mods: Adding ") + from + " ..."); + + QuaZip modZip(from); + modZip.open(QuaZip::mdUnzip); + + QuaZipFile fileInsideMod(&modZip); + QuaZipFile zipOutFile(into); + for (bool more = modZip.goToFirstFile(); more; more = modZip.goToNextFile()) + { + QString filename = modZip.getCurrentFileName(); + if (filename.contains("META-INF")) + { + QLOG_INFO() << "Skipping META-INF " << filename << " from " << from; + continue; + } + QLOG_INFO() << "Adding file " << filename << " from " << from; + + if (!fileInsideMod.open(QIODevice::ReadOnly)) + { + QLOG_ERROR() << "Failed to open " << filename << " from " << from; + return false; + } + /* + QuaZipFileInfo old_info; + fileInsideMod.getFileInfo(&old_info); + */ + QuaZipNewInfo info_out(fileInsideMod.getActualFileName()); + /* + info_out.externalAttr = old_info.externalAttr; + */ + if (!zipOutFile.open(QIODevice::WriteOnly, info_out)) + { + QLOG_ERROR() << "Failed to open " << filename << " in the jar"; + fileInsideMod.close(); + return false; + } + if (!JlCompress::copyData(fileInsideMod, zipOutFile)) + { + zipOutFile.close(); + fileInsideMod.close(); + QLOG_ERROR() << "Failed to copy data of " << filename << " into the jar"; + return false; + } + zipOutFile.close(); + fileInsideMod.close(); + } + return true; +} + + +void OneSixUpdate::fmllibsStart() +{ + // Get the mod list + OneSixInstance *inst = (OneSixInstance *)m_inst; + std::shared_ptr<VersionFinal> fullversion = inst->getFullVersion(); + bool forge_present = false; + + QString version = inst->intendedVersionId(); + auto & fmlLibsMapping = g_VersionFilterData.fmlLibsMapping; + if (!fmlLibsMapping.contains(version)) + { + assetIndexStart(); + return; + } + + auto &libList = fmlLibsMapping[version]; + + // determine if we need some libs for FML or forge + setStatus(tr("Checking for FML libraries...")); + forge_present = (fullversion->versionFile("net.minecraftforge") != nullptr); + // we don't... + if (!forge_present) + { + assetIndexStart(); + return; + } + + // now check the lib folder inside the instance for files. + for (auto &lib : libList) + { + QFileInfo libInfo(PathCombine(inst->libDir(), lib.filename)); + if (libInfo.exists()) + continue; + fmlLibsToProcess.append(lib); + } + + // if everything is in place, there's nothing to do here... + if (fmlLibsToProcess.isEmpty()) + { + assetIndexStart(); + return; + } + + // download missing libs to our place + setStatus(tr("Dowloading FML libraries...")); + auto dljob = new NetJob("FML libraries"); + auto metacache = MMC->metacache(); + for (auto &lib : fmlLibsToProcess) + { + auto entry = metacache->resolveEntry("fmllibs", lib.filename); + QString urlString = lib.ours ? URLConstants::FMLLIBS_OUR_BASE_URL + lib.filename + : URLConstants::FMLLIBS_FORGE_BASE_URL + lib.filename; + dljob->addNetAction(CacheDownload::make(QUrl(urlString), entry)); + } + + connect(dljob, SIGNAL(succeeded()), SLOT(fmllibsFinished())); + connect(dljob, SIGNAL(failed()), SLOT(fmllibsFailed())); + connect(dljob, SIGNAL(progress(qint64, qint64)), SIGNAL(progress(qint64, qint64))); + legacyDownloadJob.reset(dljob); + legacyDownloadJob->start(); +} + +void OneSixUpdate::fmllibsFinished() +{ + legacyDownloadJob.reset(); + if(!fmlLibsToProcess.isEmpty()) + { + setStatus(tr("Copying FML libraries into the instance...")); + OneSixInstance *inst = (OneSixInstance *)m_inst; + auto metacache = MMC->metacache(); + int index = 0; + for (auto &lib : fmlLibsToProcess) + { + progress(index, fmlLibsToProcess.size()); + auto entry = metacache->resolveEntry("fmllibs", lib.filename); + auto path = PathCombine(inst->libDir(), lib.filename); + if(!ensureFilePathExists(path)) + { + emitFailed(tr("Failed creating FML library folder inside the instance.")); + return; + } + if (!QFile::copy(entry->getFullPath(), PathCombine(inst->libDir(), lib.filename))) + { + emitFailed(tr("Failed copying Forge/FML library: %1.").arg(lib.filename)); + return; + } + index++; + } + progress(index, fmlLibsToProcess.size()); + } + assetIndexStart(); +} + +void OneSixUpdate::fmllibsFailed() +{ + emitFailed("Game update failed: it was impossible to fetch the required FML libraries."); + return; +}
\ No newline at end of file diff --git a/logic/OneSixUpdate.h b/logic/OneSixUpdate.h index eac882b5..00f7c135 100644 --- a/logic/OneSixUpdate.h +++ b/logic/OneSixUpdate.h @@ -21,6 +21,8 @@ #include "logic/net/NetJob.h" #include "logic/tasks/Task.h" +#include "logic/VersionFilterData.h" +#include <quazip.h> class MinecraftVersion; class OneSixInstance; @@ -42,6 +44,10 @@ slots: void jarlibFinished(); void jarlibFailed(); + void fmllibsStart(); + void fmllibsFinished(); + void fmllibsFailed(); + void assetIndexStart(); void assetIndexFinished(); void assetIndexFailed(); @@ -49,11 +55,16 @@ slots: void assetsFinished(); void assetsFailed(); + void stripJar(QString origPath, QString newPath); + bool MergeZipFiles(QuaZip *into, QString from); private: NetJobPtr specificVersionDownloadJob; NetJobPtr jarlibDownloadJob; + NetJobPtr legacyDownloadJob; // target version, determined during this task std::shared_ptr<MinecraftVersion> targetVersion; OneSixInstance *m_inst = nullptr; + QString jarHashOnEntry; + QList<FMLlib> fmlLibsToProcess; }; diff --git a/logic/URNResolver.cpp b/logic/URNResolver.cpp new file mode 100644 index 00000000..b6bdcf41 --- /dev/null +++ b/logic/URNResolver.cpp @@ -0,0 +1,98 @@ +#include "URNResolver.h" +#include <logger/Qs |
