From d587720010036e3335e321f192449808a75e958b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Mon, 21 Mar 2016 02:19:23 +0100 Subject: NOISSUE use new mojang assets locations --- logic/minecraft/AssetsUtils.cpp | 52 +++++++++++++++++++++++++++++-- logic/minecraft/AssetsUtils.h | 12 ++++++- logic/minecraft/MinecraftProfile.cpp | 22 ++++++------- logic/minecraft/MinecraftProfile.h | 9 +++--- logic/minecraft/MojangVersionFormat.cpp | 8 +++-- logic/minecraft/VersionFile.cpp | 2 +- logic/minecraft/onesix/OneSixInstance.cpp | 5 +-- logic/minecraft/onesix/OneSixUpdate.cpp | 35 +++++++-------------- logic/net/NetJob.h | 19 ++++++----- 9 files changed, 104 insertions(+), 60 deletions(-) diff --git a/logic/minecraft/AssetsUtils.cpp b/logic/minecraft/AssetsUtils.cpp index b3589cb8..7a525abe 100644 --- a/logic/minecraft/AssetsUtils.cpp +++ b/logic/minecraft/AssetsUtils.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ +#include #include #include #include @@ -23,7 +24,8 @@ #include #include "AssetsUtils.h" -#include +#include "FileSystem.h" +#include "net/MD5EtagDownload.h" namespace AssetsUtils { @@ -32,7 +34,7 @@ namespace AssetsUtils * Returns true on success, with index populated * index is undefined otherwise */ -bool loadAssetsIndexJson(QString path, AssetsIndex *index) +bool loadAssetsIndexJson(QString assetsId, QString path, AssetsIndex *index) { /* { @@ -56,6 +58,7 @@ bool loadAssetsIndexJson(QString path, AssetsIndex *index) qCritical() << "Failed to read assets index file" << path; return false; } + index->id = assetsId; // Read the file and close it. QByteArray jsonData = file.readAll(); @@ -143,7 +146,7 @@ QDir reconstructAssets(QString assetsId) << objectDir.path() << virtualDir.path() << virtualRoot.path(); AssetsIndex index; - bool loadAssetsIndex = AssetsUtils::loadAssetsIndexJson(indexPath, &index); + bool loadAssetsIndex = AssetsUtils::loadAssetsIndexJson(assetsId, indexPath, &index); if (loadAssetsIndex && index.isVirtual) { @@ -182,3 +185,46 @@ QDir reconstructAssets(QString assetsId) } } + +NetActionPtr AssetObject::getDownloadAction() +{ + QFileInfo objectFile(getLocalPath()); + if ((!objectFile.isFile()) || (objectFile.size() != size)) + { + auto objectDL = MD5EtagDownload::make(getUrl(), objectFile.filePath()); + objectDL->m_total_progress = size; + return objectDL; + } + return nullptr; +} + +QString AssetObject::getLocalPath() +{ + return "assets/objects/" + getRelPath(); +} + +QUrl AssetObject::getUrl() +{ + return QUrl("http://resources.download.minecraft.net/" + getRelPath()); +} + +QString AssetObject::getRelPath() +{ + return hash.left(2) + "/" + hash; +} + +NetJobPtr AssetsIndex::getDownloadJob() +{ + auto job = new NetJob(QObject::tr("Assets for %1").arg(id)); + for (auto &object : objects.values()) + { + auto dl = object.getDownloadAction(); + if(dl) + { + job->addNetAction(dl); + } + } + if(job->size()) + return job; + return nullptr; +} diff --git a/logic/minecraft/AssetsUtils.h b/logic/minecraft/AssetsUtils.h index 2aecd4c5..90251c2d 100644 --- a/logic/minecraft/AssetsUtils.h +++ b/logic/minecraft/AssetsUtils.h @@ -17,22 +17,32 @@ #include #include +#include "net/NetAction.h" +#include "net/NetJob.h" struct AssetObject { + QString getRelPath(); + QUrl getUrl(); + QString getLocalPath(); + NetActionPtr getDownloadAction(); + QString hash; qint64 size; }; struct AssetsIndex { + NetJobPtr getDownloadJob(); + + QString id; QMap objects; bool isVirtual = false; }; namespace AssetsUtils { -bool loadAssetsIndexJson(QString file, AssetsIndex* index); +bool loadAssetsIndexJson(QString id, QString file, AssetsIndex* index); /// Reconstruct a virtual assets folder for the given assets ID and return the folder QDir reconstructAssets(QString assetsId); } diff --git a/logic/minecraft/MinecraftProfile.cpp b/logic/minecraft/MinecraftProfile.cpp index 5fd700f2..71ece012 100644 --- a/logic/minecraft/MinecraftProfile.cpp +++ b/logic/minecraft/MinecraftProfile.cpp @@ -62,7 +62,7 @@ void MinecraftProfile::clear() { m_minecraftVersion.clear(); m_minecraftVersionType.clear(); - m_minecraftAssets.clear(); + m_minecraftAssets.reset(); m_minecraftArguments.clear(); m_tweakers.clear(); m_mainClass.clear(); @@ -420,9 +420,12 @@ void MinecraftProfile::applyMinecraftVersionType(const QString& type) applyString(type, this->m_minecraftVersionType); } -void MinecraftProfile::applyMinecraftAssets(const QString& assets) +void MinecraftProfile::applyMinecraftAssets(MojangAssetIndexInfo::Ptr assets) { - applyString(assets, this->m_minecraftAssets); + if(assets) + { + m_minecraftAssets = assets; + } } void MinecraftProfile::applyTraits(const QSet& traits) @@ -544,18 +547,11 @@ QString MinecraftProfile::getMinecraftVersionType() const return m_minecraftVersionType; } -QString MinecraftProfile::getMinecraftAssets() const +std::shared_ptr MinecraftProfile::getMinecraftAssets() const { - // HACK: deny april fools. my head hurts enough already. - QDate now = QDate::currentDate(); - bool isAprilFools = now.month() == 4 && now.day() == 1; - if (m_minecraftAssets.endsWith("_af") && !isAprilFools) - { - return m_minecraftAssets.left(m_minecraftAssets.length() - 3); - } - if (m_minecraftAssets.isEmpty()) + if(!m_minecraftAssets) { - return QLatin1Literal("legacy"); + return std::make_shared("legacy"); } return m_minecraftAssets; } diff --git a/logic/minecraft/MinecraftProfile.h b/logic/minecraft/MinecraftProfile.h index 6e7e8f74..ce0ff3cf 100644 --- a/logic/minecraft/MinecraftProfile.h +++ b/logic/minecraft/MinecraftProfile.h @@ -24,6 +24,7 @@ #include "Library.h" #include "VersionFile.h" #include "JarMod.h" +#include "MojangDownloadInfo.h" #include "multimc_logic_export.h" @@ -90,19 +91,19 @@ public: /* application of profile variables from patches */ void applyAppletClass(const QString& appletClass); void applyMinecraftArguments(const QString& minecraftArguments); void applyMinecraftVersionType(const QString& type); - void applyMinecraftAssets(const QString& assets); + void applyMinecraftAssets(MojangAssetIndexInfo::Ptr assets); void applyTraits(const QSet &traits); void applyTweakers(const QStringList &tweakers); void applyJarMods(const QList &jarMods); void applyLibrary(LibraryPtr library); void applyProblemSeverity(ProblemSeverity severity); -public: /* getters for proifile variables */ +public: /* getters for profile variables */ QString getMinecraftVersion() const; QString getMainClass() const; QString getAppletClass() const; QString getMinecraftVersionType() const; - QString getMinecraftAssets() const; + MojangAssetIndexInfo::Ptr getMinecraftAssets() const; QString getMinecraftArguments() const; const QSet & getTraits() const; const QStringList & getTweakers() const; @@ -136,7 +137,7 @@ private: /* data */ QString m_minecraftVersionType; /// Assets type - "legacy" or a version ID - QString m_minecraftAssets; + MojangAssetIndexInfo::Ptr m_minecraftAssets; /** * arguments that should be used for launching minecraft diff --git a/logic/minecraft/MojangVersionFormat.cpp b/logic/minecraft/MojangVersionFormat.cpp index 779a2b7d..41723493 100644 --- a/logic/minecraft/MojangVersionFormat.cpp +++ b/logic/minecraft/MojangVersionFormat.cpp @@ -157,11 +157,15 @@ void MojangVersionFormat::readVersionProperties(const QJsonObject &in, VersionFi } Bits::readString(in, "type", out->type); + Bits::readString(in, "assets", out->assets); if(in.contains("assetIndex")) { out->mojangAssetIndex = assetIndexFromJson(requireObject(in, "assetIndex")); } - Bits::readString(in, "assets", out->assets); + else if (!out->assets.isNull()) + { + out->mojangAssetIndex = std::make_shared(out->assets); + } out->m_releaseTime = timeFromS3Time(in.value("releaseTime").toString("")); out->m_updateTime = timeFromS3Time(in.value("time").toString("")); @@ -231,7 +235,6 @@ void MojangVersionFormat::writeVersionProperties(const VersionFile* in, QJsonObj writeString(out, "mainClass", in->mainClass); writeString(out, "minecraftArguments", in->minecraftArguments); writeString(out, "type", in->type); - writeString(out, "assets", in->assets); if(!in->m_releaseTime.isNull()) { writeString(out, "releaseTime", timeToS3Time(in->m_releaseTime)); @@ -244,6 +247,7 @@ void MojangVersionFormat::writeVersionProperties(const VersionFile* in, QJsonObj { out.insert("minimumLauncherVersion", in->minimumLauncherVersion); } + writeString(out, "assets", in->assets); if(in->mojangAssetIndex && in->mojangAssetIndex->known) { out.insert("assetIndex", assetIndexToJson(in->mojangAssetIndex)); diff --git a/logic/minecraft/VersionFile.cpp b/logic/minecraft/VersionFile.cpp index 9cda717e..451c3c8b 100644 --- a/logic/minecraft/VersionFile.cpp +++ b/logic/minecraft/VersionFile.cpp @@ -40,7 +40,7 @@ void VersionFile::applyTo(MinecraftProfile *profile) { profile->applyMinecraftVersionType(type); } - profile->applyMinecraftAssets(assets); + profile->applyMinecraftAssets(mojangAssetIndex); profile->applyTweakers(addTweakers); profile->applyJarMods(jarMods); diff --git a/logic/minecraft/onesix/OneSixInstance.cpp b/logic/minecraft/onesix/OneSixInstance.cpp index f8b274ff..328c3b38 100644 --- a/logic/minecraft/onesix/OneSixInstance.cpp +++ b/logic/minecraft/onesix/OneSixInstance.cpp @@ -125,14 +125,15 @@ QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session) QString absRootDir = QDir(minecraftRoot()).absolutePath(); token_mapping["game_directory"] = absRootDir; QString absAssetsDir = QDir("assets/").absolutePath(); - token_mapping["game_assets"] = AssetsUtils::reconstructAssets(m_profile->getMinecraftAssets()).absolutePath(); + auto assets = m_profile->getMinecraftAssets(); + token_mapping["game_assets"] = AssetsUtils::reconstructAssets(assets->id).absolutePath(); token_mapping["user_properties"] = session->serializeUserProperties(); token_mapping["user_type"] = session->user_type; // 1.7.3+ assets tokens token_mapping["assets_root"] = absAssetsDir; - token_mapping["assets_index_name"] = m_profile->getMinecraftAssets(); + token_mapping["assets_index_name"] = assets->id; QStringList parts = args_pattern.split(' ', QString::SkipEmptyParts); for (int i = 0; i < parts.length(); i++) diff --git a/logic/minecraft/onesix/OneSixUpdate.cpp b/logic/minecraft/onesix/OneSixUpdate.cpp index fe1d3a6e..10d1e294 100644 --- a/logic/minecraft/onesix/OneSixUpdate.cpp +++ b/logic/minecraft/onesix/OneSixUpdate.cpp @@ -88,9 +88,9 @@ void OneSixUpdate::assetIndexStart() setStatus(tr("Updating assets index...")); OneSixInstance *inst = (OneSixInstance *)m_inst; auto profile = inst->getMinecraftProfile(); - QString assetName = profile->getMinecraftAssets(); - QUrl indexUrl = "http://" + URLConstants::AWS_DOWNLOAD_INDEXES + assetName + ".json"; - QString localPath = assetName + ".json"; + auto assets = profile->getMinecraftAssets(); + QUrl indexUrl = assets->url; + QString localPath = assets->id + ".json"; auto job = new NetJob(tr("Asset index for %1").arg(inst->name())); auto metacache = ENV.metacache(); @@ -114,36 +114,23 @@ void OneSixUpdate::assetIndexFinished() OneSixInstance *inst = (OneSixInstance *)m_inst; auto profile = inst->getMinecraftProfile(); - QString assetName = profile->getMinecraftAssets(); + auto assets = profile->getMinecraftAssets(); - QString asset_fname = "assets/indexes/" + assetName + ".json"; - if (!AssetsUtils::loadAssetsIndexJson(asset_fname, &index)) + QString asset_fname = "assets/indexes/" + assets->id + ".json"; + // FIXME: this looks like a job for a generic validator based on json schema? + if (!AssetsUtils::loadAssetsIndexJson(assets->id, asset_fname, &index)) { auto metacache = ENV.metacache(); - auto entry = metacache->resolveEntry("asset_indexes", assetName + ".json"); + auto entry = metacache->resolveEntry("asset_indexes", assets->id + ".json"); metacache->evictEntry(entry); emitFailed(tr("Failed to read the assets index!")); } - QList dls; - for (auto object : index.objects.values()) - { - QString objectName = object.hash.left(2) + "/" + object.hash; - QFileInfo objectFile("assets/objects/" + objectName); - if ((!objectFile.isFile()) || (objectFile.size() != object.size)) - { - auto objectDL = MD5EtagDownload::make(QUrl("http://" + URLConstants::RESOURCE_BASE + objectName), objectFile.filePath()); - objectDL->m_total_progress = object.size; - dls.append(objectDL); - } - } - if (dls.size()) + auto job = index.getDownloadJob(); + if(job) { setStatus(tr("Getting the assets files from Mojang...")); - auto job = new NetJob(tr("Assets for %1").arg(inst->name())); - for (auto dl : dls) - job->addNetAction(dl); - jarlibDownloadJob.reset(job); + jarlibDownloadJob = job; connect(jarlibDownloadJob.get(), SIGNAL(succeeded()), SLOT(assetsFinished())); connect(jarlibDownloadJob.get(), &NetJob::failed, this, &OneSixUpdate::assetsFailed); connect(jarlibDownloadJob.get(), SIGNAL(progress(qint64, qint64)), SIGNAL(progress(qint64, qint64))); diff --git a/logic/net/NetJob.h b/logic/net/NetJob.h index 45f6dacf..afbe9ff3 100644 --- a/logic/net/NetJob.h +++ b/logic/net/NetJob.h @@ -35,16 +35,15 @@ class MULTIMC_LOGIC_EXPORT NetJob : public Task public: explicit NetJob(QString job_name) : Task(), m_job_name(job_name) {} virtual ~NetJob() {} - template bool addNetAction(T action) + bool addNetAction(NetActionPtr action) { - NetActionPtr base = std::static_pointer_cast(action); - base->m_index_within_job = downloads.size(); + action->m_index_within_job = downloads.size(); downloads.append(action); part_info pi; { - pi.current_progress = base->currentProgress(); - pi.total_progress = base->totalProgress(); - pi.failures = base->numberOfFailures(); + pi.current_progress = action->currentProgress(); + pi.total_progress = action->totalProgress(); + pi.failures = action->numberOfFailures(); } parts_progress.append(pi); total_progress += pi.total_progress; @@ -52,11 +51,11 @@ public: if (isRunning()) { setProgress(current_progress, total_progress); - connect(base.get(), SIGNAL(succeeded(int)), SLOT(partSucceeded(int))); - connect(base.get(), SIGNAL(failed(int)), SLOT(partFailed(int))); - connect(base.get(), SIGNAL(netActionProgress(int, qint64, qint64)), + connect(action.get(), SIGNAL(succeeded(int)), SLOT(partSucceeded(int))); + connect(action.get(), SIGNAL(failed(int)), SLOT(partFailed(int))); + connect(action.get(), SIGNAL(netActionProgress(int, qint64, qint64)), SLOT(partProgress(int, qint64, qint64))); - base->start(); + action->start(); } return true; } -- cgit v1.2.3