diff options
author | Petr Mrázek <peterix@gmail.com> | 2013-08-24 03:09:46 +0200 |
---|---|---|
committer | Petr Mrázek <peterix@gmail.com> | 2013-08-24 03:09:46 +0200 |
commit | e3b55067eb51ee82e72b41a1919406d768e00b89 (patch) | |
tree | a22158bc63242191463d450d1a3f37eeb37bba5b /logic/LegacyUpdate.cpp | |
parent | b78123166627139777fbd206866ee0d1c8bcd040 (diff) | |
download | MultiMC-e3b55067eb51ee82e72b41a1919406d768e00b89.tar MultiMC-e3b55067eb51ee82e72b41a1919406d768e00b89.tar.gz MultiMC-e3b55067eb51ee82e72b41a1919406d768e00b89.tar.lz MultiMC-e3b55067eb51ee82e72b41a1919406d768e00b89.tar.xz MultiMC-e3b55067eb51ee82e72b41a1919406d768e00b89.zip |
Legacy jar reassembly, base of proper custom jar support
Diffstat (limited to 'logic/LegacyUpdate.cpp')
-rw-r--r-- | logic/LegacyUpdate.cpp | 221 |
1 files changed, 130 insertions, 91 deletions
diff --git a/logic/LegacyUpdate.cpp b/logic/LegacyUpdate.cpp index a748bad3..9644cb80 100644 --- a/logic/LegacyUpdate.cpp +++ b/logic/LegacyUpdate.cpp @@ -4,9 +4,11 @@ #include "BaseInstance.h" #include "LegacyInstance.h" #include "net/NetWorker.h" +#include "ModList.h" #include <pathutils.h> #include <quazip.h> #include <quazipfile.h> +#include <JlCompress.h> LegacyUpdate::LegacyUpdate ( BaseInstance* inst, QObject* parent ) : BaseUpdate ( inst, parent ) {} @@ -22,7 +24,7 @@ void LegacyUpdate::lwjglStart() lwjglVersion = inst->lwjglVersion(); lwjglTargetPath = PathCombine("lwjgl", lwjglVersion ); - lwjglNativesPath = PathCombine( lwjglTargetPath, "natives/"); + lwjglNativesPath = PathCombine( lwjglTargetPath, "natives"); // if the 'done' file exists, we don't have to download this again QFileInfo doneFile(PathCombine(lwjglTargetPath, "done")); @@ -112,7 +114,7 @@ void LegacyUpdate::extractLwjgl() { // make sure the directories are there - bool success = ensurePathExists(lwjglNativesPath); + bool success = ensureFolderPathExists(lwjglNativesPath); if(!success) { @@ -201,33 +203,14 @@ void LegacyUpdate::lwjglFailed() void LegacyUpdate::jarStart() { - setStatus("Checking ..."); LegacyInstance * inst = (LegacyInstance *) m_inst; - QString current_version_id = inst->currentVersionId(); - QString intended_version_id = inst->intendedVersionId(); - bool shouldUpdate = inst->shouldUpdate(); - if(!shouldUpdate) + if(!inst->shouldUpdate() || inst->shouldUseCustomBaseJar()) { - emitSucceeded(); + ModTheJar(); return; } - // nuke the backup file, we are replacing the base jar anyway - QFile mc_backup(inst->mcBackup()); - if (mc_backup.exists()) - { - mc_backup.remove(); - } - - // Get a pointer to the version object that corresponds to the instance's version. - auto targetVersion = MinecraftVersionList::getMainList().findVersion(intended_version_id); - - if(!targetVersion) - { - emitFailed("Not a valid version:" + intended_version_id); - return; - } - + setStatus("Checking for jar updates..."); // Make directories QDir binDir(inst->binDir()); if (!binDir.exists() && !binDir.mkpath(".")) @@ -239,14 +222,11 @@ void LegacyUpdate::jarStart() // Build a list of URLs that will need to be downloaded. setStatus("Downloading new minecraft.jar"); - // This will be either 'minecraft' or the version number, depending on where - // we're downloading from. - QString jarFilename = "minecraft"; - QString download_path = PathCombine(inst->minecraftRoot(), "bin/minecraft.jar"); - QString urlstr("http://s3.amazonaws.com/Minecraft.Download/versions/"); - urlstr += targetVersion->descriptor + "/" + targetVersion->descriptor + ".jar"; - auto dljob = DownloadJob::create(QUrl(urlstr), download_path); + QString intended_version_id = inst->intendedVersionId(); + urlstr += intended_version_id + "/" + intended_version_id + ".jar"; + + auto dljob = DownloadJob::create(QUrl(urlstr), inst->defaultBaseJar()); legacyDownloadJob.reset(new JobList()); legacyDownloadJob->add(dljob); @@ -259,7 +239,7 @@ void LegacyUpdate::jarStart() void LegacyUpdate::jarFinished() { // process the jar - emitSucceeded(); + ModTheJar(); } void LegacyUpdate::jarFailed() @@ -268,74 +248,132 @@ void LegacyUpdate::jarFailed() emitFailed("Failed to download the minecraft jar. Try again later."); } +bool LegacyUpdate::MergeZipFiles( QuaZip* into, QFileInfo from, QSet< QString >& contained ) +{ + setStatus("Installing mods - Adding " + from.fileName()); + + QuaZip modZip(from.filePath()); + 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")) + continue; + if(contained.contains(filename)) + continue; + contained.insert(filename); + qDebug() << "Adding file " << filename << " from " << from.fileName(); + + if(!fileInsideMod.open(QIODevice::ReadOnly)) + { + return false; + } + if(!zipOutFile.open(QIODevice::WriteOnly, QuaZipNewInfo(fileInsideMod.getActualFileName()))) + { + fileInsideMod.close(); + return false; + } + if(!JlCompress::copyData(fileInsideMod, zipOutFile)) + { + zipOutFile.close(); + fileInsideMod.close(); + return false; + } + zipOutFile.close(); + fileInsideMod.close(); + } + return true; +} + void LegacyUpdate::ModTheJar() { - /* LegacyInstance * inst = (LegacyInstance *) m_inst; + + if(!inst->shouldRebuild()) + { + emitSucceeded(); + return; + } + // Get the mod list - auto modList = inst->getJarModList(); + auto modList = inst->jarModList(); - QFileInfo mcBin(inst->binDir()); - QFileInfo mcJar(inst->mcJar()); - QFileInfo mcBackup(inst->mcBackup()); + QFileInfo runnableJar (inst->runnableJar()); + QFileInfo baseJar (inst->baseJar()); + bool base_is_custom = inst->shouldUseCustomBaseJar(); // Nothing to do if there are no jar mods to install, no backup and just the mc jar - if(mcJar.isFile() && !mcBackup.exists() && modList->empty()) + if(base_is_custom) { - inst->setShouldRebuild(false); - emitSucceeded(); - return; + // yes, this can happen if the instance only has the runnable jar and not the base jar + // it *could* be assumed that such an instance is vanilla, but that wouldn't be safe + // because that's not something mmc4 guarantees + if(runnableJar.isFile() && !baseJar.exists() && modList->empty()) + { + inst->setShouldRebuild(false); + emitSucceeded(); + return; + } + + setStatus("Installing mods - backing up minecraft.jar..."); + if (!baseJar.exists() && !QFile::copy(runnableJar.filePath(), baseJar.filePath())) + { + emitFailed("Failed to back up minecraft.jar"); + return; + } } - setStatus("Installing mods - backing up minecraft.jar..."); - if (!mcBackup.exists() && !QFile::copy(mcJar.absoluteFilePath(), mcBackup.absoluteFilePath()) ) + if (!baseJar.exists()) { - emitFailed("Failed to back up minecraft.jar"); + emitFailed("The base jar " + baseJar.filePath() + " does not exist"); return; } - if (mcJar.isFile() && !QFile::remove(mcJar.absoluteFilePath())) + if (runnableJar.exists() && !QFile::remove(runnableJar.filePath())) { emitFailed("Failed to delete old minecraft.jar"); return; } + //TaskStep(); // STEP 1 setStatus("Installing mods - Opening minecraft.jar"); - wxFFileOutputStream jarStream(mcJar.absoluteFilePath()); - wxZipOutputStream zipOut(jarStream); - + QuaZip zipOut(runnableJar.filePath()); + if(!zipOut.open(QuaZip::mdCreate)) + { + QFile::remove(runnableJar.filePath()); + emitFailed("Failed to open the minecraft.jar for modding"); + return; + } // Files already added to the jar. // These files will be skipped. QSet<QString> addedFiles; // Modify the jar setStatus("Installing mods - Adding mod files..."); - for (ModList::const_reverse_iterator iter = modList->rbegin(); iter != modList->rend(); iter++) + for (int i = modList->size() - 1; i >= 0; i--) { - wxFileName modFileName = iter->GetFileName(); - setStatus("Installing mods - Adding " + modFileName.GetFullName()); - if (iter->GetModType() == Mod::ModType::MOD_ZIPFILE) + auto &mod = modList->operator[](i); + if (mod.type() == Mod::MOD_ZIPFILE) { - wxFFileInputStream modStream(modFileName.GetFullPath()); - wxZipInputStream zipStream(modStream); - std::unique_ptr<wxZipEntry> entry; - while (entry.reset(zipStream.GetNextEntry()), entry.get() != NULL) + if(!MergeZipFiles(&zipOut, mod.filename(), addedFiles)) { - if (entry->IsDir()) - continue; - - wxString name = entry->GetName(); - if (addedFiles.count(name) == 0) - { - if (!zipOut.CopyEntry(entry.release(), zipStream)) - break; - addedFiles.insert(name); - } + zipOut.close(); + QFile::remove(runnableJar.filePath()); + emitFailed("Failed to add " + mod.filename().fileName() + " to the jar."); + return; } } - else + else if (mod.type() == Mod::MOD_SINGLEFILE) { + zipOut.close(); + QFile::remove(runnableJar.filePath()); + emitFailed("Loose files are NOT supported as jar mods."); + return; + /* wxFileName destFileName = modFileName; destFileName.MakeRelativeTo(m_inst->GetInstModsDir().GetFullPath()); wxString destFile = destFileName.GetFullPath(); @@ -348,34 +386,35 @@ void LegacyUpdate::ModTheJar() addedFiles.insert(destFile); } + */ } - } - - { - wxFFileInputStream inStream(mcBackup.GetFullPath()); - wxZipInputStream zipIn(inStream); - - std::auto_ptr<wxZipEntry> entry; - while (entry.reset(zipIn.GetNextEntry()), entry.get() != NULL) + else if (mod.type() == Mod::MOD_FOLDER) { - wxString name = entry->GetName(); - - if (!name.Matches("META-INF*") && - addedFiles.count(name) == 0) - { - if (!zipOut.CopyEntry(entry.release(), zipIn)) - break; - addedFiles.insert(name); - } + zipOut.close(); + QFile::remove(runnableJar.filePath()); + emitFailed("Folders are NOT supported as jar mods."); + return; } } + if(!MergeZipFiles(&zipOut, baseJar, addedFiles)) + { + zipOut.close(); + QFile::remove(runnableJar.filePath()); + emitFailed("Failed to insert minecraft.jar contents."); + return; + } + // Recompress the jar - TaskStep(); // STEP 3 - SetStatus(_("Installing mods - Recompressing jar...")); - - inst->SetNeedsRebuild(false); - inst->UpdateVersion(true); - return (ExitCode)1; - */ + zipOut.close(); + if(zipOut.getZipError()!=0) + { + QFile::remove(runnableJar.filePath()); + emitFailed("Failed to finalize minecraft.jar!"); + return; + } + inst->setShouldRebuild(false); + //inst->UpdateVersion(true); + emitSucceeded(); + return; }
\ No newline at end of file |