diff options
Diffstat (limited to 'api/logic/minecraft/liteloader/LiteLoaderVersionList.cpp')
-rw-r--r-- | api/logic/minecraft/liteloader/LiteLoaderVersionList.cpp | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/api/logic/minecraft/liteloader/LiteLoaderVersionList.cpp b/api/logic/minecraft/liteloader/LiteLoaderVersionList.cpp new file mode 100644 index 00000000..b0c9736a --- /dev/null +++ b/api/logic/minecraft/liteloader/LiteLoaderVersionList.cpp @@ -0,0 +1,276 @@ +/* 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 "LiteLoaderVersionList.h" +#include <minecraft/onesix/OneSixVersionFormat.h> +#include "Env.h" +#include "net/URLConstants.h" +#include "Exception.h" + +#include <QtXml> + +#include <QJsonDocument> +#include <QJsonObject> +#include <QJsonArray> +#include <QJsonValue> +#include <QJsonParseError> + +#include <QtAlgorithms> + +#include <QtNetwork> + +LiteLoaderVersionList::LiteLoaderVersionList(QObject *parent) : BaseVersionList(parent) +{ +} + +Task *LiteLoaderVersionList::getLoadTask() +{ + return new LLListLoadTask(this); +} + +bool LiteLoaderVersionList::isLoaded() +{ + return m_loaded; +} + +const BaseVersionPtr LiteLoaderVersionList::at(int i) const +{ + return m_vlist.at(i); +} + +int LiteLoaderVersionList::count() const +{ + return m_vlist.count(); +} + +static bool cmpVersions(BaseVersionPtr first, BaseVersionPtr second) +{ + auto left = std::dynamic_pointer_cast<LiteLoaderVersion>(first); + auto right = std::dynamic_pointer_cast<LiteLoaderVersion>(second); + return left->timestamp > right->timestamp; +} + +void LiteLoaderVersionList::sortVersions() +{ + beginResetModel(); + std::sort(m_vlist.begin(), m_vlist.end(), cmpVersions); + endResetModel(); +} + +QVariant LiteLoaderVersionList::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (index.row() > count()) + return QVariant(); + + auto version = std::dynamic_pointer_cast<LiteLoaderVersion>(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->mcVersion; + + case RecommendedRole: + return version->isLatest; + + default: + return QVariant(); + } +} + +QList<BaseVersionList::ModelRoles> LiteLoaderVersionList::providesRoles() +{ + return {VersionPointerRole, VersionRole, VersionIdRole, ParentGameVersionRole, RecommendedRole}; +} + +BaseVersionPtr LiteLoaderVersionList::getLatestStable() const +{ + for (int i = 0; i < m_vlist.length(); i++) + { + auto ver = std::dynamic_pointer_cast<LiteLoaderVersion>(m_vlist.at(i)); + if (ver->isLatest) + { + return m_vlist.at(i); + } + } + return BaseVersionPtr(); +} + +void LiteLoaderVersionList::updateListData(QList<BaseVersionPtr> versions) +{ + beginResetModel(); + m_vlist = versions; + m_loaded = true; + std::sort(m_vlist.begin(), m_vlist.end(), cmpVersions); + endResetModel(); +} + +LLListLoadTask::LLListLoadTask(LiteLoaderVersionList *vlist) +{ + m_list = vlist; +} + +LLListLoadTask::~LLListLoadTask() +{ +} + +void LLListLoadTask::executeTask() +{ + setStatus(tr("Loading LiteLoader version list...")); + auto job = new NetJob("Version index"); + // we do not care if the version is stale or not. + auto liteloaderEntry = ENV.metacache()->resolveEntry("liteloader", "versions.json"); + + // verify by poking the server. + liteloaderEntry->setStale(true); + + job->addNetAction(listDownload = CacheDownload::make(QUrl(URLConstants::LITELOADER_URL), + liteloaderEntry)); + + connect(listDownload.get(), SIGNAL(failed(int)), SLOT(listFailed())); + + listJob.reset(job); + connect(listJob.get(), SIGNAL(succeeded()), SLOT(listDownloaded())); + connect(listJob.get(), SIGNAL(progress(qint64, qint64)), SIGNAL(progress(qint64, qint64))); + listJob->start(); +} + +void LLListLoadTask::listFailed() +{ + emitFailed("Failed to load LiteLoader version list."); + return; +} + +void LLListLoadTask::listDownloaded() +{ + QByteArray data; + { + auto dlJob = listDownload; + auto filename = std::dynamic_pointer_cast<CacheDownload>(dlJob)->getTargetFilepath(); + QFile listFile(filename); + if (!listFile.open(QIODevice::ReadOnly)) + { + emitFailed("Failed to open the LiteLoader version list."); + return; + } + data = listFile.readAll(); + listFile.close(); + dlJob.reset(); + } + + QJsonParseError jsonError; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); + + 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; + } + + const QJsonObject root = jsonDoc.object(); + + // Now, get the array of versions. + if (!root.value("versions").isObject()) + { + emitFailed("Error parsing version list JSON: missing 'versions' object"); + return; + } + + auto meta = root.value("meta").toObject(); + QString description = meta.value("description").toString(tr("This is a lightweight loader for mods that don't change game mechanics.")); + QString defaultUrl = meta.value("url").toString("http://dl.liteloader.com"); + QString authors = meta.value("authors").toString("Mumfrey"); + auto versions = root.value("versions").toObject(); + + QList<BaseVersionPtr> tempList; + for (auto vIt = versions.begin(); vIt != versions.end(); ++vIt) + { + const QString mcVersion = vIt.key(); + QString latest; + const QJsonObject artefacts = vIt.value() + .toObject() + .value("artefacts") + .toObject() + .value("com.mumfrey:liteloader") + .toObject(); + QList<BaseVersionPtr> perMcVersionList; + for (auto aIt = artefacts.begin(); aIt != artefacts.end(); ++aIt) + { + const QString identifier = aIt.key(); + const QJsonObject artefact = aIt.value().toObject(); + if (identifier == "latest") + { + latest = artefact.value("version").toString(); + continue; + } + LiteLoaderVersionPtr version(new LiteLoaderVersion()); + version->version = artefact.value("version").toString(); + version->file = artefact.value("file").toString(); + version->mcVersion = mcVersion; + version->md5 = artefact.value("md5").toString(); + version->timestamp = artefact.value("timestamp").toString().toInt(); + version->tweakClass = artefact.value("tweakClass").toString(); + version->authors = authors; + version->description = description; + version->defaultUrl = defaultUrl; + const QJsonArray libs = artefact.value("libraries").toArray(); + for (auto lIt = libs.begin(); lIt != libs.end(); ++lIt) + { + auto libobject = (*lIt).toObject(); + try + { + auto lib = OneSixVersionFormat::libraryFromJson(libobject, "versions.json"); + // hack to make liteloader 1.7.10_00 work + if(lib->rawName() == GradleSpecifier("org.ow2.asm:asm-all:5.0.3")) + { + lib->setRepositoryURL("http://repo.maven.apache.org/maven2/"); + } + version->libraries.append(lib); + } + catch (Exception &e) + { + qCritical() << "Couldn't read JSON object:"; + continue; + } + } + perMcVersionList.append(version); + } + for (auto version : perMcVersionList) + { + auto v = std::dynamic_pointer_cast<LiteLoaderVersion>(version); + v->isLatest = v->version == latest; + } + tempList.append(perMcVersionList); + } + m_list->updateListData(tempList); + + emitSucceeded(); +} |