From 4c3bd416c65ec887209fa06b0a5634099b77f322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Mon, 5 May 2014 00:10:59 +0200 Subject: Much change, very jarmod. --- logic/OneSixUpdate.cpp | 214 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 212 insertions(+), 2 deletions(-) (limited to 'logic/OneSixUpdate.cpp') 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 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 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 -- cgit v1.2.3