From 17ad1e64f824fba6d8f153191effdb2af7d387c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sat, 27 Feb 2016 19:58:40 +0100 Subject: NOISSUE move files into paths that make more sense --- logic/forge/ForgeInstaller.cpp | 441 -------------------------------------- logic/forge/ForgeInstaller.h | 52 ----- logic/forge/ForgeMirror.h | 10 - logic/forge/ForgeMirrors.cpp | 118 ---------- logic/forge/ForgeMirrors.h | 58 ----- logic/forge/ForgeVersion.cpp | 55 ----- logic/forge/ForgeVersion.h | 42 ---- logic/forge/ForgeVersionList.cpp | 449 --------------------------------------- logic/forge/ForgeVersionList.h | 89 -------- logic/forge/ForgeXzDownload.cpp | 389 --------------------------------- logic/forge/ForgeXzDownload.h | 66 ------ logic/forge/LegacyForge.cpp | 56 ----- logic/forge/LegacyForge.h | 25 --- 13 files changed, 1850 deletions(-) delete mode 100644 logic/forge/ForgeInstaller.cpp delete mode 100644 logic/forge/ForgeInstaller.h delete mode 100644 logic/forge/ForgeMirror.h delete mode 100644 logic/forge/ForgeMirrors.cpp delete mode 100644 logic/forge/ForgeMirrors.h delete mode 100644 logic/forge/ForgeVersion.cpp delete mode 100644 logic/forge/ForgeVersion.h delete mode 100644 logic/forge/ForgeVersionList.cpp delete mode 100644 logic/forge/ForgeVersionList.h delete mode 100644 logic/forge/ForgeXzDownload.cpp delete mode 100644 logic/forge/ForgeXzDownload.h delete mode 100644 logic/forge/LegacyForge.cpp delete mode 100644 logic/forge/LegacyForge.h (limited to 'logic/forge') diff --git a/logic/forge/ForgeInstaller.cpp b/logic/forge/ForgeInstaller.cpp deleted file mode 100644 index 78acb8d4..00000000 --- a/logic/forge/ForgeInstaller.cpp +++ /dev/null @@ -1,441 +0,0 @@ -/* Copyright 2013-2015 MultiMC Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ForgeInstaller.h" -#include "minecraft/MinecraftProfile.h" -#include "minecraft/GradleSpecifier.h" -#include "net/HttpMetaCache.h" -#include "tasks/Task.h" -#include "minecraft/OneSixInstance.h" -#include "forge/ForgeVersionList.h" -#include "minecraft/VersionFilterData.h" -#include "Env.h" -#include "Exception.h" -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -ForgeInstaller::ForgeInstaller() : BaseInstaller() -{ -} - -void ForgeInstaller::prepare(const QString &filename, const QString &universalUrl) -{ - std::shared_ptr newVersion; - m_universal_url = universalUrl; - - QuaZip zip(filename); - if (!zip.open(QuaZip::mdUnzip)) - return; - - QuaZipFile file(&zip); - - // read the install profile - if (!zip.setCurrentFile("install_profile.json")) - return; - - QJsonParseError jsonError; - if (!file.open(QIODevice::ReadOnly)) - return; - QJsonDocument jsonDoc = QJsonDocument::fromJson(file.readAll(), &jsonError); - file.close(); - if (jsonError.error != QJsonParseError::NoError) - return; - - if (!jsonDoc.isObject()) - return; - - QJsonObject root = jsonDoc.object(); - - auto installVal = root.value("install"); - auto versionInfoVal = root.value("versionInfo"); - if (!installVal.isObject() || !versionInfoVal.isObject()) - return; - - // read the forge version info - { - newVersion = MinecraftProfile::fromJson(versionInfoVal.toObject()); - if (!newVersion) - return; - } - - QJsonObject installObj = installVal.toObject(); - QString libraryName = installObj.value("path").toString(); - internalPath = installObj.value("filePath").toString(); - m_forgeVersionString = installObj.value("version").toString().remove("Forge").trimmed(); - - // where do we put the library? decode the mojang path - GradleSpecifier lib(libraryName); - - auto cacheentry = ENV.metacache()->resolveEntry("libraries", lib.toPath()); - finalPath = "libraries/" + lib.toPath(); - if (!FS::ensureFilePathExists(finalPath)) - return; - - if (!zip.setCurrentFile(internalPath)) - return; - if (!file.open(QIODevice::ReadOnly)) - return; - { - QByteArray data = file.readAll(); - // extract file - QSaveFile extraction(finalPath); - if (!extraction.open(QIODevice::WriteOnly)) - return; - if (extraction.write(data) != data.size()) - return; - if (!extraction.commit()) - return; - QCryptographicHash md5sum(QCryptographicHash::Md5); - md5sum.addData(data); - - cacheentry->stale = false; - cacheentry->md5sum = md5sum.result().toHex().constData(); - ENV.metacache()->updateEntry(cacheentry); - } - file.close(); - - m_forge_json = newVersion; - m_forge_json->id = installObj.value("minecraft").toString(); -} - -bool ForgeInstaller::add(OneSixInstance *to) -{ - if (!BaseInstaller::add(to)) - { - return false; - } - - QJsonObject obj; - obj.insert("order", 5); - - if (!m_forge_json) - return false; - int sliding_insert_window = 0; - { - QJsonArray librariesPlus; - // A blacklist - QSet blacklist{"authlib", "realms"}; - // - QList xzlist{"org.scala-lang", "com.typesafe"}; - // for each library in the version we are adding (except for the blacklisted) - for (auto lib : m_forge_json->libraries) - { - QString libName = lib->artifactId(); - QString rawName = lib->rawName(); - - // ignore lwjgl libraries. - if (g_VersionFilterData.lwjglWhitelist.contains(lib->artifactPrefix())) - continue; - // ignore other blacklisted (realms, authlib) - if (blacklist.contains(libName)) - continue; - - // WARNING: This could actually break. - // if this is the actual forge lib, set an absolute url for the download - if (m_forge_version->type == ForgeVersion::Gradle) - { - if (libName == "forge") - { - lib->setClassifier("universal"); - } - else if (libName == "minecraftforge") - { - QString forgeCoord("net.minecraftforge:forge:%1:universal"); - // using insane form of the MC version... - QString longVersion = - m_forge_version->mcver + "-" + m_forge_version->jobbuildver; - GradleSpecifier spec(forgeCoord.arg(longVersion)); - lib->setRawName(spec); - } - } - else - { - if (libName.contains("minecraftforge")) - { - lib->setAbsoluteUrl(m_universal_url); - } - } - - // WARNING: This could actually break. - // mark bad libraries based on the xzlist above - for (auto entry : xzlist) - { - qDebug() << "Testing " << rawName << " : " << entry; - if (rawName.startsWith(entry)) - { - lib->setHint("forge-pack-xz"); - break; - } - } - - QJsonObject libObj = lib->toJson(); - - bool found = false; - bool equals = false; - // find an entry that matches this one - for (auto tolib : to->getMinecraftProfile()->vanillaLibraries) - { - if (tolib->artifactId() != libName) - continue; - found = true; - if (tolib->toJson() == libObj) - { - equals = true; - } - // replace lib - libObj.insert("insert", QString("replace")); - break; - } - if (equals) - { - continue; - } - if (!found) - { - // add lib - libObj.insert("insert", QString("prepend")); - if (lib->artifactId() == "minecraftforge" || lib->artifactId() == "forge") - { - libObj.insert("MMC-depend", QString("hard")); - } - sliding_insert_window++; - } - librariesPlus.prepend(libObj); - } - obj.insert("+libraries", librariesPlus); - obj.insert("mainClass", m_forge_json->mainClass); - QString args = m_forge_json->minecraftArguments; - QStringList tweakers; - { - QRegularExpression expression("--tweakClass ([a-zA-Z0-9\\.]*)"); - QRegularExpressionMatch match = expression.match(args); - while (match.hasMatch()) - { - tweakers.append(match.captured(1)); - args.remove(match.capturedStart(), match.capturedLength()); - match = expression.match(args); - } - } - if (!args.isEmpty() && args != to->getMinecraftProfile()->vanillaMinecraftArguments) - { - obj.insert("minecraftArguments", args); - } - if (!tweakers.isEmpty()) - { - obj.insert("+tweakers", QJsonArray::fromStringList(tweakers)); - } - if (!m_forge_json->processArguments.isEmpty() && - m_forge_json->processArguments != to->getMinecraftProfile()->vanillaProcessArguments) - { - obj.insert("processArguments", m_forge_json->processArguments); - } - } - - obj.insert("name", QString("Forge")); - obj.insert("fileId", id()); - obj.insert("version", m_forgeVersionString); - obj.insert("mcVersion", to->intendedVersionId()); - - QFile file(filename(to->instanceRoot())); - if (!file.open(QFile::WriteOnly)) - { - qCritical() << "Error opening" << file.fileName() - << "for reading:" << file.errorString(); - return false; - } - file.write(QJsonDocument(obj).toJson()); - file.close(); - - return true; -} - -bool ForgeInstaller::addLegacy(OneSixInstance *to) -{ - if (!BaseInstaller::add(to)) - { - return false; - } - auto entry = ENV.metacache()->resolveEntry("minecraftforge", m_forge_version->filename()); - finalPath = FS::PathCombine(to->jarModsDir(), m_forge_version->filename()); - if (!FS::ensureFilePathExists(finalPath)) - { - return false; - } - if (!QFile::copy(entry->getFullPath(), finalPath)) - { - return false; - } - QJsonObject obj; - obj.insert("order", 5); - { - QJsonArray jarmodsPlus; - { - QJsonObject libObj; - libObj.insert("name", m_forge_version->universal_filename); - jarmodsPlus.append(libObj); - } - obj.insert("+jarMods", jarmodsPlus); - } - - obj.insert("name", QString("Forge")); - obj.insert("fileId", id()); - obj.insert("version", m_forge_version->jobbuildver); - obj.insert("mcVersion", to->intendedVersionId()); - if (g_VersionFilterData.fmlLibsMapping.contains(m_forge_version->mcver)) - { - QJsonArray traitsPlus; - traitsPlus.append(QString("legacyFML")); - obj.insert("+traits", traitsPlus); - } - auto fullversion = to->getMinecraftProfile(); - fullversion->remove("net.minecraftforge"); - - QFile file(filename(to->instanceRoot())); - if (!file.open(QFile::WriteOnly)) - { - qCritical() << "Error opening" << file.fileName() - << "for reading:" << file.errorString(); - return false; - } - file.write(QJsonDocument(obj).toJson()); - file.close(); - return true; -} - -class ForgeInstallTask : public Task -{ - Q_OBJECT -public: - ForgeInstallTask(ForgeInstaller *installer, OneSixInstance *instance, - BaseVersionPtr version, QObject *parent = 0) - : Task(parent), m_installer(installer), m_instance(instance), m_version(version) - { - } - -protected: - void executeTask() override - { - setStatus(tr("Installing Forge...")); - ForgeVersionPtr forgeVersion = std::dynamic_pointer_cast(m_version); - if (!forgeVersion) - { - emitFailed(tr("Unknown error occured")); - return; - } - prepare(forgeVersion); - } - void prepare(ForgeVersionPtr forgeVersion) - { - auto entry = ENV.metacache()->resolveEntry("minecraftforge", forgeVersion->filename()); - auto installFunction = [this, entry, forgeVersion]() - { - if (!install(entry, forgeVersion)) - { - qCritical() << "Failure installing Forge"; - emitFailed(tr("Failure to install Forge")); - } - else - { - reload(); - } - }; - - /* - * HACK IF the local non-stale file is too small, mark is as stale - * - * This fixes some problems with bad files acquired because of unhandled HTTP redirects - * in old versions of MultiMC. - */ - if (!entry->stale) - { - QFileInfo localFile(entry->getFullPath()); - if (localFile.size() <= 0x4000) - { - entry->stale = true; - } - } - - if (entry->stale) - { - NetJob *fjob = new NetJob("Forge download"); - fjob->addNetAction(CacheDownload::make(forgeVersion->url(), entry)); - connect(fjob, &NetJob::progress, this, &Task::setProgress); - connect(fjob, &NetJob::status, this, &Task::setStatus); - connect(fjob, &NetJob::failed, [this](QString reason) - { emitFailed(tr("Failure to download Forge:\n%1").arg(reason)); }); - connect(fjob, &NetJob::succeeded, installFunction); - fjob->start(); - } - else - { - installFunction(); - } - } - bool install(const std::shared_ptr &entry, const ForgeVersionPtr &forgeVersion) - { - if (forgeVersion->usesInstaller()) - { - QString forgePath = entry->getFullPath(); - m_installer->prepare(forgePath, forgeVersion->universal_url); - return m_installer->add(m_instance); - } - else - return m_installer->addLegacy(m_instance); - } - void reload() - { - try - { - m_instance->reloadProfile(); - emitSucceeded(); - } - catch (Exception &e) - { - emitFailed(e.cause()); - } - catch (...) - { - emitFailed(tr("Failed to load the version description file for reasons unknown.")); - } - } - -private: - ForgeInstaller *m_installer; - OneSixInstance *m_instance; - BaseVersionPtr m_version; -}; - -Task *ForgeInstaller::createInstallTask(OneSixInstance *instance, - BaseVersionPtr version, QObject *parent) -{ - if (!version) - { - return nullptr; - } - m_forge_version = std::dynamic_pointer_cast(version); - return new ForgeInstallTask(this, instance, version, parent); -} - -#include "ForgeInstaller.moc" diff --git a/logic/forge/ForgeInstaller.h b/logic/forge/ForgeInstaller.h deleted file mode 100644 index 0de762b6..00000000 --- a/logic/forge/ForgeInstaller.h +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright 2013-2015 MultiMC Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include "BaseInstaller.h" - -#include -#include - -#include "multimc_logic_export.h" - -class MinecraftProfile; -class ForgeInstallTask; -struct ForgeVersion; - -class MULTIMC_LOGIC_EXPORT ForgeInstaller : public BaseInstaller -{ - friend class ForgeInstallTask; -public: - ForgeInstaller(); - virtual ~ForgeInstaller(){} - virtual Task *createInstallTask(OneSixInstance *instance, BaseVersionPtr version, QObject *parent) override; - virtual QString id() const override { return "net.minecraftforge"; } - -protected: - void prepare(const QString &filename, const QString &universalUrl); - bool add(OneSixInstance *to) override; - bool addLegacy(OneSixInstance *to); - -private: - // the parsed version json, read from the installer - std::shared_ptr m_forge_json; - // the actual forge version - std::shared_ptr m_forge_version; - QString internalPath; - QString finalPath; - QString m_forgeVersionString; - QString m_universal_url; -}; diff --git a/logic/forge/ForgeMirror.h b/logic/forge/ForgeMirror.h deleted file mode 100644 index 2518dffe..00000000 --- a/logic/forge/ForgeMirror.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include - -struct ForgeMirror -{ - QString name; - QString logo_url; - QString website_url; - QString mirror_url; -}; \ No newline at end of file diff --git a/logic/forge/ForgeMirrors.cpp b/logic/forge/ForgeMirrors.cpp deleted file mode 100644 index a2fc2c62..00000000 --- a/logic/forge/ForgeMirrors.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include "Env.h" -#include "ForgeMirrors.h" -#include -#include -#include - -ForgeMirrors::ForgeMirrors(QList &libs, NetJobPtr parent_job, - QString mirrorlist) -{ - m_libs = libs; - m_parent_job = parent_job; - m_url = QUrl(mirrorlist); - m_status = Job_NotStarted; -} - -void ForgeMirrors::start() -{ - qDebug() << "Downloading " << m_url.toString(); - QNetworkRequest request(m_url); - request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Uncached)"); - auto worker = ENV.qnam(); - QNetworkReply *rep = worker->get(request); - - m_reply.reset(rep); - connect(rep, SIGNAL(downloadProgress(qint64, qint64)), - SLOT(downloadProgress(qint64, qint64))); - connect(rep, SIGNAL(finished()), SLOT(downloadFinished())); - connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), - SLOT(downloadError(QNetworkReply::NetworkError))); - connect(rep, SIGNAL(readyRead()), SLOT(downloadReadyRead())); -} - -void ForgeMirrors::downloadError(QNetworkReply::NetworkError error) -{ - // error happened during download. - qCritical() << "Error getting URL:" << m_url.toString().toLocal8Bit() - << "Network error: " << error; - m_status = Job_Failed; -} - -void ForgeMirrors::downloadFinished() -{ - // if the download succeeded - if (m_status != Job_Failed) - { - // nothing went wrong... ? - parseMirrorList(); - return; - } - // else the download failed, we use a fixed list - else - { - m_status = Job_Finished; - m_reply.reset(); - deferToFixedList(); - return; - } -} - -void ForgeMirrors::deferToFixedList() -{ - m_mirrors.clear(); - m_mirrors.append( - {"Minecraft Forge", "http://files.minecraftforge.net/forge_logo.png", - "http://files.minecraftforge.net/", "http://files.minecraftforge.net/maven/"}); - m_mirrors.append({"Creeper Host", - "http://files.minecraftforge.net/forge_logo.png", - "https://www.creeperhost.net/link.php?id=1", - "http://new.creeperrepo.net/forge/maven/"}); - injectDownloads(); - emit succeeded(m_index_within_job); -} - -void ForgeMirrors::parseMirrorList() -{ - m_status = Job_Finished; - auto data = m_reply->readAll(); - m_reply.reset(); - auto dataLines = data.split('\n'); - for(auto line: dataLines) - { - auto elements = line.split('!'); - if (elements.size() == 4) - { - m_mirrors.append({elements[0],elements[1],elements[2],elements[3]}); - } - } - if(!m_mirrors.size()) - deferToFixedList(); - injectDownloads(); - emit succeeded(m_index_within_job); -} - -void ForgeMirrors::injectDownloads() -{ - // shuffle the mirrors randomly - std::random_device rd; - std::mt19937 rng(rd()); - std::shuffle(m_mirrors.begin(), m_mirrors.end(), rng); - - // tell parent to download the libs - for(auto lib: m_libs) - { - lib->setMirrors(m_mirrors); - m_parent_job->addNetAction(lib); - } -} - -void ForgeMirrors::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) -{ - m_total_progress = bytesTotal; - m_progress = bytesReceived; - emit netActionProgress(m_index_within_job, bytesReceived, bytesTotal); -} - -void ForgeMirrors::downloadReadyRead() -{ -} diff --git a/logic/forge/ForgeMirrors.h b/logic/forge/ForgeMirrors.h deleted file mode 100644 index e7c90fa5..00000000 --- a/logic/forge/ForgeMirrors.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright 2013-2015 MultiMC Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include "net/NetAction.h" -#include "net/HttpMetaCache.h" -#include "net/NetJob.h" -#include "forge/ForgeXzDownload.h" -#include -#include -typedef std::shared_ptr ForgeMirrorsPtr; - -class ForgeMirrors : public NetAction -{ - Q_OBJECT -public: - QList m_libs; - NetJobPtr m_parent_job; - QList m_mirrors; - -public: - explicit ForgeMirrors(QList &libs, NetJobPtr parent_job, - QString mirrorlist); - static ForgeMirrorsPtr make(QList &libs, NetJobPtr parent_job, - QString mirrorlist) - { - return ForgeMirrorsPtr(new ForgeMirrors(libs, parent_job, mirrorlist)); - } - virtual ~ForgeMirrors(){}; -protected -slots: - virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); - virtual void downloadError(QNetworkReply::NetworkError error); - virtual void downloadFinished(); - virtual void downloadReadyRead(); - -private: - void parseMirrorList(); - void deferToFixedList(); - void injectDownloads(); - -public -slots: - virtual void start(); -}; diff --git a/logic/forge/ForgeVersion.cpp b/logic/forge/ForgeVersion.cpp deleted file mode 100644 index b859a28c..00000000 --- a/logic/forge/ForgeVersion.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "ForgeVersion.h" -#include "minecraft/VersionFilterData.h" -#include - -QString ForgeVersion::name() -{ - return "Forge " + jobbuildver; -} - -QString ForgeVersion::descriptor() -{ - return universal_filename; -} - -QString ForgeVersion::typeString() const -{ - if (is_recommended) - return QObject::tr("Recommended"); - return QString(); -} - -bool ForgeVersion::operator<(BaseVersion &a) -{ - ForgeVersion *pa = dynamic_cast(&a); - if (!pa) - return true; - return m_buildnr < pa->m_buildnr; -} - -bool ForgeVersion::operator>(BaseVersion &a) -{ - ForgeVersion *pa = dynamic_cast(&a); - if (!pa) - return false; - return m_buildnr > pa->m_buildnr; -} - -bool ForgeVersion::usesInstaller() -{ - if(installer_url.isEmpty()) - return false; - if(g_VersionFilterData.forgeInstallerBlacklist.contains(mcver)) - return false; - return true; -} - -QString ForgeVersion::filename() -{ - return usesInstaller() ? installer_filename : universal_filename; -} - -QString ForgeVersion::url() -{ - return usesInstaller() ? installer_url : universal_url; -} diff --git a/logic/forge/ForgeVersion.h b/logic/forge/ForgeVersion.h deleted file mode 100644 index e77d32f1..00000000 --- a/logic/forge/ForgeVersion.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once -#include -#include -#include "BaseVersion.h" - -struct ForgeVersion; -typedef std::shared_ptr ForgeVersionPtr; - -struct ForgeVersion : public BaseVersion -{ - virtual QString descriptor() override; - virtual QString name() override; - virtual QString typeString() const override; - virtual bool operator<(BaseVersion &a) override; - virtual bool operator>(BaseVersion &a) override; - - QString filename(); - QString url(); - - enum - { - Invalid, - Legacy, - Gradle - } type = Invalid; - - bool usesInstaller(); - - int m_buildnr = 0; - QString branch; - QString universal_url; - QString changelog_url; - QString installer_url; - QString jobbuildver; - QString mcver; - QString mcver_sane; - QString universal_filename; - QString installer_filename; - bool is_recommended = false; -}; - -Q_DECLARE_METATYPE(ForgeVersionPtr) diff --git a/logic/forge/ForgeVersionList.cpp b/logic/forge/ForgeVersionList.cpp deleted file mode 100644 index a05ced99..00000000 --- a/logic/forge/ForgeVersionList.cpp +++ /dev/null @@ -1,449 +0,0 @@ -/* Copyright 2013-2015 MultiMC Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "forge/ForgeVersionList.h" -#include "forge/ForgeVersion.h" -#include "net/NetJob.h" -#include "net/URLConstants.h" -#include "Env.h" - -#include -#include -#include - -#include - -ForgeVersionList::ForgeVersionList(QObject *parent) : BaseVersionList(parent) -{ -} - -Task *ForgeVersionList::getLoadTask() -{ - return new ForgeListLoadTask(this); -} - -bool ForgeVersionList::isLoaded() -{ - return m_loaded; -} - -const BaseVersionPtr ForgeVersionList::at(int i) const -{ - return m_vlist.at(i); -} - -int ForgeVersionList::count() const -{ - return m_vlist.count(); -} - -int ForgeVersionList::columnCount(const QModelIndex &parent) const -{ - return 1; -} - -QVariant ForgeVersionList::data(const QModelIndex &index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - if (index.row() > count()) - return QVariant(); - - auto version = std::dynamic_pointer_cast(m_vlist[index.row()]); - switch (role) - { - case VersionPointerRole: - return qVariantFromValue(m_vlist[index.row()]); - - case VersionRole: - return version->name(); - - case VersionIdRole: - return version->descriptor(); - - case ParentGameVersionRole: - return version->mcver_sane; - - case RecommendedRole: - return version->is_recommended; - - case BranchRole: - return version->branch; - - default: - return QVariant(); - } -} - -QList ForgeVersionList::providesRoles() -{ - return {VersionPointerRole, VersionRole, VersionIdRole, ParentGameVersionRole, RecommendedRole, BranchRole}; -} - -BaseVersionPtr ForgeVersionList::getLatestStable() const -{ - return BaseVersionPtr(); -} - -void ForgeVersionList::updateListData(QList versions) -{ - beginResetModel(); - m_vlist = versions; - m_loaded = true; - endResetModel(); - // NOW SORT!! - // sort(); -} - -void ForgeVersionList::sortVersions() -{ - // NO-OP for now -} - -ForgeListLoadTask::ForgeListLoadTask(ForgeVersionList *vlist) : Task() -{ - m_list = vlist; -} - -void ForgeListLoadTask::executeTask() -{ - setStatus(tr("Fetching Forge version lists...")); - auto job = new NetJob("Version index"); - // we do not care if the version is stale or not. - auto forgeListEntry = ENV.metacache()->resolveEntry("minecraftforge", "list.json"); - auto gradleForgeListEntry = ENV.metacache()->resolveEntry("minecraftforge", "json"); - - // verify by poking the server. - forgeListEntry->stale = true; - gradleForgeListEntry->stale = true; - - job->addNetAction(listDownload = CacheDownload::make(QUrl(URLConstants::FORGE_LEGACY_URL), - forgeListEntry)); - job->addNetAction(gradleListDownload = CacheDownload::make( - QUrl(URLConstants::FORGE_GRADLE_URL), gradleForgeListEntry)); - - connect(listDownload.get(), SIGNAL(failed(int)), SLOT(listFailed())); - connect(gradleListDownload.get(), SIGNAL(failed(int)), SLOT(gradleListFailed())); - - listJob.reset(job); - connect(listJob.get(), SIGNAL(succeeded()), SLOT(listDownloaded())); - connect(listJob.get(), SIGNAL(progress(qint64, qint64)), SIGNAL(progress(qint64, qint64))); - listJob->start(); -} - -bool ForgeListLoadTask::abort() -{ - return listJob->abort(); -} - -bool ForgeListLoadTask::parseForgeList(QList &out) -{ - QByteArray data; - { - auto dlJob = listDownload; - auto filename = std::dynamic_pointer_cast(dlJob)->getTargetFilepath(); - QFile listFile(filename); - if (!listFile.open(QIODevice::ReadOnly)) - { - return false; - } - data = listFile.readAll(); - dlJob.reset(); - } - - QJsonParseError jsonError; - QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); - - if (jsonError.error != QJsonParseError::NoError) - { - emitFailed("Error parsing version list JSON:" + jsonError.errorString()); - return false; - } - - if (!jsonDoc.isObject()) - { - emitFailed("Error parsing version list JSON: JSON root is not an object"); - return false; - } - - QJsonObject root = jsonDoc.object(); - - // Now, get the array of versions. - if (!root.value("builds").isArray()) - { - emitFailed( - "Error parsing version list JSON: version list object is missing 'builds' array"); - return false; - } - QJsonArray builds = root.value("builds").toArray(); - - for (int i = 0; i < builds.count(); i++) - { - // Load the version info. - if (!builds[i].isObject()) - { - // FIXME: log this somewhere - continue; - } - QJsonObject obj = builds[i].toObject(); - int build_nr = obj.value("build").toDouble(0); - if (!build_nr) - continue; - QJsonArray files = obj.value("files").toArray(); - QString url, jobbuildver, mcver, buildtype, universal_filename; - QString changelog_url, installer_url; - QString installer_filename; - bool valid = false; - for (int j = 0; j < files.count(); j++) - { - if (!files[j].isObject()) - { - continue; - } - QJsonObject file = files[j].toObject(); - buildtype = file.value("buildtype").toString(); - if ((buildtype == "client" || buildtype == "universal") && !valid) - { - mcver = file.value("mcver").toString(); - url = file.value("url").toString(); - jobbuildver = file.value("jobbuildver").toString(); - int lastSlash = url.lastIndexOf('/'); - universal_filename = url.mid(lastSlash + 1); - valid = true; - } - else if (buildtype == "changelog") - { - QString ext = file.value("ext").toString(); - if (ext.isEmpty()) - { - continue; - } - changelog_url = file.value("url").toString(); - } - else if (buildtype == "installer") - { - installer_url = file.value("url").toString(); - int lastSlash = installer_url.lastIndexOf('/'); - installer_filename = installer_url.mid(lastSlash + 1); - } - } - if (valid) - { - // Now, we construct the version object and add it to the list. - std::shared_ptr fVersion(new ForgeVersion()); - fVersion->universal_url = url; - fVersion->changelog_url = changelog_url; - fVersion->installer_url = installer_url; - fVersion->jobbuildver = jobbuildver; - fVersion->mcver = fVersion->mcver_sane = mcver; - fVersion->installer_filename = installer_filename; - fVersion->universal_filename = universal_filename; - fVersion->m_buildnr = build_nr; - fVersion->type = ForgeVersion::Legacy; - out.append(fVersion); - } - } - - return true; -} - -bool ForgeListLoadTask::parseForgeGradleList(QList &out) -{ - QMap> lookup; - QByteArray data; - { - auto dlJob = gradleListDownload; - auto filename = std::dynamic_pointer_cast(dlJob)->getTargetFilepath(); - QFile listFile(filename); - if (!listFile.open(QIODevice::ReadOnly)) - { - return false; - } - data = listFile.readAll(); - dlJob.reset(); - } - - QJsonParseError jsonError; - QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); - - if (jsonError.error != QJsonParseError::NoError) - { - emitFailed("Error parsing gradle version list JSON:" + jsonError.errorString()); - return false; - } - - if (!jsonDoc.isObject()) - { - emitFailed("Error parsing gradle version list JSON: JSON root is not an object"); - return false; - } - - QJsonObject root = jsonDoc.object(); - - // we probably could hard code these, but it might still be worth doing it this way - const QString webpath = root.value("webpath").toString(); - const QString artifact = root.value("artifact").toString(); - - QJsonObject numbers = root.value("number").toObject(); - for (auto it = numbers.begin(); it != numbers.end(); ++it) - { - QJsonObject number = it.value().toObject(); - std::shared_ptr fVersion(new ForgeVersion()); - fVersion->m_buildnr = number.value("build").toDouble(); - if(fVersion->m_buildnr >= 953 && fVersion->m_buildnr <= 965) - { - qDebug() << fVersion->m_buildnr; - } - fVersion->jobbuildver = number.value("version").toString(); - fVersion->branch = number.value("branch").toString(""); - fVersion->mcver = number.value("mcversion").toString(); - fVersion->universal_filename = ""; - fVersion->installer_filename = ""; - // HACK: here, we fix the minecraft version used by forge. - // HACK: this will inevitably break (later) - // FIXME: replace with a dictionary - fVersion->mcver_sane = fVersion->mcver; - fVersion->mcver_sane.replace("_pre", "-pre"); - - QString universal_filename, installer_filename; - QJsonArray files = number.value("files").toArray(); - for (auto fIt = files.begin(); fIt != files.end(); ++fIt) - { - // TODO with gradle we also get checksums, use them - QJsonArray file = (*fIt).toArray(); - if (file.size() < 3) - { - continue; - } - - QString extension = file.at(0).toString(); - QString part = file.at(1).toString(); - QString checksum = file.at(2).toString(); - - // insane form of mcver is used here - QString longVersion = fVersion->mcver + "-" + fVersion->jobbuildver; - if (!fVersion->branch.isEmpty()) - { - longVersion = longVersion + "-" + fVersion->branch; - } - QString filename = artifact + "-" + longVersion + "-" + part + "." + extension; - - QString url = QString("%1/%2/%3") - .arg(webpath) - .arg(longVersion) - .arg(filename); - - if (part == "installer") - { - fVersion->installer_url = url; - installer_filename = filename; - } - else if (part == "universal") - { - fVersion->universal_url = url; - universal_filename = filename; - } - else if (part == "changelog") - { - fVersion->changelog_url = url; - } - } - if (fVersion->installer_url.isEmpty() && fVersion->universal_url.isEmpty()) - { - continue; - } - fVersion->universal_filename = universal_filename; - fVersion->installer_filename = installer_filename; - fVersion->type = ForgeVersion::Gradle; - out.append(fVersion); - lookup[fVersion->m_buildnr] = fVersion; - } - QJsonObject promos = root.value("promos").toObject(); - for (auto it = promos.begin(); it != promos.end(); ++it) - { - QString key = it.key(); - int build = it.value().toInt(); - QRegularExpression regexp("^(?[0-9]+(.[0-9]+)*)-(?