void LegacyUpdate::lwjglFailed() { emitFailed("Bad stuff happened while trying to get the lwjgl libs..."); }
void LegacyUpdate::jarFailed() { // bad, bad emitFailed("Failed to download the minecraft jar. Try again later."); }
void LegacyUpdate::fmllibsFailed() { emitFailed("Game update failed: it was impossible to fetch the required FML libraries."); return; }
void LegacyUpdate::extractLwjgl() { // make sure the directories are there bool success = ensureFolderPathExists(lwjglNativesPath); if (!success) { emitFailed("Failed to extract the lwjgl libs - error when creating required folders."); return; } QuaZip zip("lwjgl.zip"); if (!zip.open(QuaZip::mdUnzip)) { emitFailed("Failed to extract the lwjgl libs - not a valid archive."); return; } // and now we are going to access files inside it QuaZipFile file(&zip); const QString jarNames[] = {"jinput.jar", "lwjgl_util.jar", "lwjgl.jar"}; for (bool more = zip.goToFirstFile(); more; more = zip.goToNextFile()) { if (!file.open(QIODevice::ReadOnly)) { zip.close(); emitFailed("Failed to extract the lwjgl libs - error while reading archive."); return; } QuaZipFileInfo info; QString name = file.getActualFileName(); if (name.endsWith('/')) { file.close(); continue; } QString destFileName; // Look for the jars for (int i = 0; i < 3; i++) { if (name.endsWith(jarNames[i])) { destFileName = PathCombine(lwjglTargetPath, jarNames[i]); } } // Not found? look for the natives if (destFileName.isEmpty()) { #ifdef Q_OS_WIN32 QString nativesDir = "windows"; #else #ifdef Q_OS_MAC QString nativesDir = "macosx"; #else QString nativesDir = "linux"; #endif #endif if (name.contains(nativesDir)) { int lastSlash = name.lastIndexOf('/'); int lastBackSlash = name.lastIndexOf('\\'); if (lastSlash != -1) name = name.mid(lastSlash + 1); else if (lastBackSlash != -1) name = name.mid(lastBackSlash + 1); destFileName = PathCombine(lwjglNativesPath, name); } } // Now if destFileName is still empty, go to the next file. if (!destFileName.isEmpty()) { setStatus(tr("Installing new LWJGL - extracting ") + name + "..."); QFile output(destFileName); output.open(QIODevice::WriteOnly); output.write(file.readAll()); // FIXME: wste of memory!? output.close(); } file.close(); // do not forget to close! } zip.close(); m_reply.reset(); QFile doneFile(PathCombine(lwjglTargetPath, "done")); doneFile.open(QIODevice::WriteOnly); doneFile.write("done."); doneFile.close(); }
void OneSixUpdate::assetsFailed() { emitFailed("Failed to download assets!"); }
void OneSixUpdate::jarlibStart() { setStatus(tr("Getting the library files from Mojang...")); QLOG_INFO() << m_inst->name() << ": downloading libraries"; OneSixInstance *inst = (OneSixInstance *)m_inst; bool successful = inst->reloadFullVersion(); if (!successful) { emitFailed("Failed to load the version description file. It might be " "corrupted, missing or simply too new."); return; } // Build a list of URLs that will need to be downloaded. std::shared_ptr<OneSixVersion> version = inst->getFullVersion(); // minecraft.jar for this version { QString version_id = version->id; QString localPath = version_id + "/" + version_id + ".jar"; QString urlstr = "http://" + URLConstants::AWS_DOWNLOAD_VERSIONS + localPath; auto job = new NetJob("Libraries for instance " + inst->name()); auto metacache = MMC->metacache(); auto entry = metacache->resolveEntry("versions", localPath); job->addNetAction(CacheDownload::make(QUrl(urlstr), entry)); jarlibDownloadJob.reset(job); } auto libs = version->getActiveNativeLibs(); libs.append(version->getActiveNormalLibs()); auto metacache = MMC->metacache(); QList<ForgeXzDownloadPtr> ForgeLibs; for (auto lib : libs) { if (lib->hint() == "local") continue; QString raw_storage = lib->storagePath(); QString raw_dl = lib->downloadUrl(); auto f = [&](QString storage, QString dl) { auto entry = metacache->resolveEntry("libraries", storage); if (entry->stale) { if (lib->hint() == "forge-pack-xz") { ForgeLibs.append(ForgeXzDownload::make(storage, entry)); } else { jarlibDownloadJob->addNetAction(CacheDownload::make(dl, entry)); } } }; if (raw_storage.contains("${arch}")) { QString cooked_storage = raw_storage; QString cooked_dl = raw_dl; f(cooked_storage.replace("${arch}", "32"), cooked_dl.replace("${arch}", "32")); cooked_storage = raw_storage; cooked_dl = raw_dl; f(cooked_storage.replace("${arch}", "64"), cooked_dl.replace("${arch}", "64")); } else { f(raw_storage, raw_dl); } } // TODO: think about how to propagate this from the original json file... or IF AT ALL QString forgeMirrorList = "http://files.minecraftforge.net/mirror-brand.list"; if (!ForgeLibs.empty()) { jarlibDownloadJob->addNetAction( ForgeMirrors::make(ForgeLibs, jarlibDownloadJob, forgeMirrorList)); } connect(jarlibDownloadJob.get(), SIGNAL(succeeded()), SLOT(jarlibFinished())); connect(jarlibDownloadJob.get(), SIGNAL(failed()), SLOT(jarlibFailed())); connect(jarlibDownloadJob.get(), SIGNAL(progress(qint64, qint64)), SIGNAL(progress(qint64, qint64))); jarlibDownloadJob->start(); }
void OneSixUpdate::assetIndexFailed() { emitFailed("Failed to download the assets index!"); }
void OneSixUpdate::versionFileFailed() { emitFailed("Failed to download the version description. Try again."); }
void AssetsMigrateTask::executeTask() { this->setStatus(tr("Migrating legacy assets...")); this->setProgress(0); QDir assets_dir("assets"); if (!assets_dir.exists()) { emitFailed("Assets directory didn't exist"); return; } assets_dir.setFilter(QDir::AllEntries | QDir::NoDotAndDotDot); int base_length = assets_dir.path().length(); QList<QString> blacklist = {"indexes", "objects", "virtual"}; if (!assets_dir.exists("objects")) assets_dir.mkdir("objects"); QDir objects_dir("assets/objects"); QDirIterator iterator(assets_dir, QDirIterator::Subdirectories); int successes = 0; int failures = 0; while (iterator.hasNext()) { QString currentDir = iterator.next(); currentDir = currentDir.remove(0, base_length + 1); bool ignore = false; for (QString blacklisted : blacklist) { if (currentDir.startsWith(blacklisted)) ignore = true; } if (!iterator.fileInfo().isDir() && !ignore) { QString filename = iterator.filePath(); QFile input(filename); input.open(QIODevice::ReadOnly | QIODevice::WriteOnly); QString sha1sum = QCryptographicHash::hash(input.readAll(), QCryptographicHash::Sha1) .toHex() .constData(); QString object_name = filename.remove(0, base_length + 1); QLOG_DEBUG() << "Processing" << object_name << ":" << sha1sum << input.size(); QString object_tlk = sha1sum.left(2); QString object_tlk_dir = objects_dir.path() + "/" + object_tlk; QDir tlk_dir(object_tlk_dir); if (!tlk_dir.exists()) objects_dir.mkdir(object_tlk); QString new_filename = tlk_dir.path() + "/" + sha1sum; QFile new_object(new_filename); if (!new_object.exists()) { bool rename_success = input.rename(new_filename); QLOG_DEBUG() << " Doesn't exist, copying to" << new_filename << ":" << QString::number(rename_success); if (rename_success) successes++; else failures++; } else { input.remove(); QLOG_DEBUG() << " Already exists, deleting original and not copying."; } this->setProgress(100 * ((successes + failures) / (float) this->m_expected)); } } if (successes + failures == 0) { this->setProgress(100); QLOG_DEBUG() << "No legacy assets needed importing."; } else { QLOG_DEBUG() << "Finished copying legacy assets:" << successes << "successes and" << failures << "failures."; this->setStatus("Cleaning up legacy assets..."); this->setProgress(100); QDirIterator cleanup_iterator(assets_dir); while (cleanup_iterator.hasNext()) { QString currentDir = cleanup_iterator.next(); currentDir = currentDir.remove(0, base_length + 1); bool ignore = false; for (QString blacklisted : blacklist) { if (currentDir.startsWith(blacklisted)) ignore = true; } if (cleanup_iterator.fileInfo().isDir() && !ignore) { QString path = cleanup_iterator.filePath(); QDir folder(path); QLOG_DEBUG() << "Cleaning up legacy assets folder:" << path; folder.removeRecursively(); } } } if(failures > 0) { emitFailed(QString("Failed to migrate %1 legacy assets").arg(failures)); } else { emitSucceeded(); } }
void MCVListLoadTask::list_downloaded() { if(vlistReply->error() != QNetworkReply::QNetworkReply::NoError) { vlistReply->deleteLater(); emitFailed("Failed to load Minecraft main version list" + vlistReply->errorString()); return; } QJsonParseError jsonError; QJsonDocument jsonDoc = QJsonDocument::fromJson(vlistReply->readAll(), &jsonError); vlistReply->deleteLater(); if (jsonError.error != QJsonParseError::NoError) { emitFailed("Error parsing version list JSON:" + jsonError.errorString()); return; } if(!jsonDoc.isObject()) { emitFailed("Error parsing version list JSON: jsonDoc is not an object"); return; } QJsonObject root = jsonDoc.object(); // Get the ID of the latest release and the latest snapshot. if(!root.value("latest").isObject()) { emitFailed("Error parsing version list JSON: version list is missing 'latest' object"); return; } QJsonObject latest = root.value("latest").toObject(); QString latestReleaseID = latest.value("release").toString(""); QString latestSnapshotID = latest.value("snapshot").toString(""); if(latestReleaseID.isEmpty()) { emitFailed("Error parsing version list JSON: latest release field is missing"); return; } if(latestSnapshotID.isEmpty()) { emitFailed("Error parsing version list JSON: latest snapshot field is missing"); return; } // Now, get the array of versions. if(!root.value("versions").isArray()) { emitFailed("Error parsing version list JSON: version list object is missing 'versions' array"); return; } QJsonArray versions = root.value("versions").toArray(); QList<InstVersionPtr > tempList; for (int i = 0; i < versions.count(); i++) { bool is_snapshot = false; bool is_latest = false; // Load the version info. if(!versions[i].isObject()) { //FIXME: log this somewhere continue; } QJsonObject version = versions[i].toObject(); QString versionID = version.value("id").toString(""); QString versionTimeStr = version.value("releaseTime").toString(""); QString versionTypeStr = version.value("type").toString(""); if(versionID.isEmpty() || versionTimeStr.isEmpty() || versionTypeStr.isEmpty()) { //FIXME: log this somewhere continue; } // Parse the timestamp. QDateTime versionTime = timeFromS3Time(versionTimeStr); if(!versionTime.isValid()) { //FIXME: log this somewhere continue; } // Parse the type. MinecraftVersion::VersionType versionType; // OneSix or Legacy. use filter to determine type if (versionTypeStr == "release") { versionType = legacyWhitelist.contains(versionID)?MinecraftVersion::Legacy:MinecraftVersion::OneSix; is_latest = (versionID == latestReleaseID); is_snapshot = false; } else if(versionTypeStr == "snapshot") // It's a snapshot... yay { versionType = legacyWhitelist.contains(versionID)?MinecraftVersion::Legacy:MinecraftVersion::OneSix; is_latest = (versionID == latestSnapshotID); is_snapshot = true; } else if(versionTypeStr == "old_alpha") { versionType = MinecraftVersion::Nostalgia; is_latest = false; is_snapshot = false; } else if(versionTypeStr == "old_beta") { versionType = MinecraftVersion::Legacy; is_latest = false; is_snapshot = false; } else { //FIXME: log this somewhere continue; } // Get the download URL. QString dlUrl = QString(MCVLIST_URLBASE) + versionID + "/"; // Now, we construct the version object and add it to the list. QSharedPointer<MinecraftVersion> mcVersion(new MinecraftVersion()); mcVersion->name = mcVersion->descriptor = versionID; mcVersion->timestamp = versionTime.toMSecsSinceEpoch(); mcVersion->download_url = dlUrl; mcVersion->is_latest = is_latest; mcVersion->is_snapshot = is_snapshot; mcVersion->type = versionType; tempList.append(mcVersion); } m_list->updateListData(tempList); emitSucceeded(); return; }
void OneSixUpdate::jarlibStart() { OneSixInstance *inst = (OneSixInstance *)m_inst; bool successful = inst->reloadFullVersion(); if (!successful) { emitFailed("Failed to load the version description file (version.json). It might be " "corrupted, missing or simply too new."); return; } std::shared_ptr<OneSixVersion> version = inst->getFullVersion(); // download the right jar, save it in versions/$version/$version.jar QString urlstr("http://s3.amazonaws.com/Minecraft.Download/versions/"); urlstr += version->id + "/" + version->id + ".jar"; QString targetstr("versions/"); targetstr += version->id + "/" + version->id + ".jar"; auto job = new NetJob("Libraries for instance " + inst->name()); job->addNetAction(FileDownload::make(QUrl(urlstr), targetstr)); jarlibDownloadJob.reset(job); auto libs = version->getActiveNativeLibs(); libs.append(version->getActiveNormalLibs()); auto metacache = MMC->metacache(); QList<ForgeXzDownloadPtr> ForgeLibs; bool already_forge_xz = false; for (auto lib : libs) { if (lib->hint() == "local") continue; auto entry = metacache->resolveEntry("libraries", lib->storagePath()); if (entry->stale) { if (lib->hint() == "forge-pack-xz") { ForgeLibs.append(ForgeXzDownload::make(lib->storagePath(), entry)); } else { jarlibDownloadJob->addNetAction(CacheDownload::make(lib->downloadUrl(), entry)); } } } // TODO: think about how to propagate this from the original json file... or IF AT ALL QString forgeMirrorList = "http://files.minecraftforge.net/mirror-brand.list"; if (!ForgeLibs.empty()) { jarlibDownloadJob->addNetAction( ForgeMirrors::make(ForgeLibs, jarlibDownloadJob, forgeMirrorList)); } connect(jarlibDownloadJob.get(), SIGNAL(succeeded()), SLOT(jarlibFinished())); connect(jarlibDownloadJob.get(), SIGNAL(failed()), SLOT(jarlibFailed())); connect(jarlibDownloadJob.get(), SIGNAL(progress(qint64, qint64)), SIGNAL(progress(qint64, qint64))); jarlibDownloadJob->start(); }