/* 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 #include "Env.h" #include "net/URLConstants.h" #include "Exception.h" #include #include #include #include #include #include #include #include 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(first); auto right = std::dynamic_pointer_cast(second); return left->timestamp > right->timestamp; } VersionFilePtr LiteLoaderVersion::getVersionFile() { auto f = std::make_shared(); f->mainClass = "net.minecraft.launchwrapper.Launch"; f->addTweakers += tweakClass; f->order = 10; f->libraries = libraries; f->name = "LiteLoader"; f->fileId = "com.mumfrey.liteloader"; f->version = version; f->minecraftVersion = mcVersion; return f; } 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(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 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(m_vlist.at(i)); if (ver->isLatest) { return m_vlist.at(i); } } return BaseVersionPtr(); } void LiteLoaderVersionList::updateListData(QList 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 = Net::Download::makeCached(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 filename = listDownload->getTargetFilepath(); QFile listFile(filename); if (!listFile.open(QIODevice::ReadOnly)) { emitFailed("Failed to open the LiteLoader version list."); return; } data = listFile.readAll(); listFile.close(); listDownload.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 tempList; for (auto vIt = versions.begin(); vIt != versions.end(); ++vIt) { const QString mcVersion = vIt.key(); const QJsonObject versionObject = vIt.value().toObject(); auto processArtefacts = [&](QJsonObject artefacts, bool notSnapshots) { QString latest; QList 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->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; // FIXME: ignores bad libraries and continues loading } } auto liteloaderLib = std::make_shared("com.mumfrey:liteloader:" + version->version); liteloaderLib->setRepositoryURL("http://dl.liteloader.com/versions/"); if(!notSnapshots) { liteloaderLib->setHint("always-stale"); } version->libraries.append(liteloaderLib); perMcVersionList.append(version); } if(notSnapshots) { for (auto version : perMcVersionList) { auto v = std::dynamic_pointer_cast(version); v->isLatest = v->version == latest; } } tempList.append(perMcVersionList); }; // are there actually released versions for this mc version? if(versionObject.contains("artefacts")) { const QJsonObject artefacts = versionObject.value("artefacts").toObject().value("com.mumfrey:liteloader").toObject(); processArtefacts(artefacts, true); } if(versionObject.contains("snapshots")) { QJsonObject artefacts = versionObject.value("snapshots").toObject().value("com.mumfrey:liteloader").toObject(); processArtefacts(artefacts, false); /* LiteLoaderVersionPtr version(new LiteLoaderVersion()); version->version = mcVersion + "-SNAPSHOT"; version->mcVersion = mcVersion; version->md5 = QString(); // FIXME: not available, unable to check version->timestamp = QDateTime::currentMSecsSinceEpoch() / 1000LL; version->tweakClass = "com.mumfrey.liteloader.launch.LiteLoaderTweaker"; // FIXME: guessing here, no data available version->authors = authors; version->description = description; version->defaultUrl = defaultUrl; const QJsonArray libs = snapshots.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; // FIXME: ignores bad libraries and continues loading } } auto liteloaderLib = std::make_shared("com.mumfrey:liteloader:" + version->version); liteloaderLib->setHint("always-stale"); liteloaderLib->setRepositoryURL("http://dl.liteloader.com/versions/"); version->libraries.append(liteloaderLib); tempList.append(version); */ } } m_list->updateListData(tempList); emitSucceeded(); }