From 18853ca3fa185f5fe5288a1d0c8ed6cf8c678007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Mon, 22 Jul 2013 02:01:56 +0200 Subject: [PATCH] Parsing the version files, part I --- libmultimc/CMakeLists.txt | 6 ++ libmultimc/include/fullversion.h | 68 ++++++++++++++ libmultimc/include/fullversionfactory.h | 23 +++++ libmultimc/include/library.h | 18 ++++ libmultimc/src/fullversion.cpp | 4 + libmultimc/src/fullversionfactory.cpp | 113 ++++++++++++++++++++++++ libmultimc/src/gameupdatetask.cpp | 71 ++------------- libmultimc/src/library.cpp | 18 ++++ 8 files changed, 258 insertions(+), 63 deletions(-) create mode 100644 libmultimc/include/fullversion.h create mode 100644 libmultimc/include/fullversionfactory.h create mode 100644 libmultimc/include/library.h create mode 100644 libmultimc/src/fullversion.cpp create mode 100644 libmultimc/src/fullversionfactory.cpp create mode 100644 libmultimc/src/library.cpp diff --git a/libmultimc/CMakeLists.txt b/libmultimc/CMakeLists.txt index 0209f8a4..8adee1ec 100644 --- a/libmultimc/CMakeLists.txt +++ b/libmultimc/CMakeLists.txt @@ -32,6 +32,9 @@ include/instversionlist.h include/minecraftversion.h include/minecraftversionlist.h +include/library.h +include/fullversion.h +include/fullversionfactory.h # Tasks include/task.h @@ -63,6 +66,9 @@ src/instversionlist.cpp src/minecraftversion.cpp src/minecraftversionlist.cpp +src/library.cpp +src/fullversion.cpp +src/fullversionfactory.cpp # Tasks src/task.cpp diff --git a/libmultimc/include/fullversion.h b/libmultimc/include/fullversion.h new file mode 100644 index 00000000..b1de02a3 --- /dev/null +++ b/libmultimc/include/fullversion.h @@ -0,0 +1,68 @@ +#pragma once +#include +#include + +class FullVersion +{ +public: + FullVersion() + { + minimumLauncherVersion = 0xDEADBEEF; + isLegacy = false; + } + // the ID - determines which jar to use! ACTUALLY IMPORTANT! + QString id; + // do we actually care about parsing this? + QString time; + // I don't think we do. + QString releaseTime; + // eh, not caring - "release" or "snapshot" + QString type; + /* + * DEPRECATED: Old versions of the new vanilla launcher used this + * ex: "username_session_version" + */ + QString processArguments; + /* + * arguments that should be used for launching minecraft + * + * ex: "--username ${auth_player_name} --session ${auth_session} + * --version ${version_name} --gameDir ${game_directory} --assetsDir ${game_assets}" + */ + QString minecraftArguments; + /* + * the minimum launcher version required by this version ... current is 4 (at point of writing) + */ + int minimumLauncherVersion; + /* + * The main class to load first + */ + QString mainClass; + + // the list of libs. just the names for now. expand to full-blown strutures! + QStringList libraries; + + // is this actually a legacy version? if so, none of the other stuff here will be ever used. + // added by FullVersionFactory + bool isLegacy; + +/* +FIXME: add support for those rules here? Looks like a pile of quick hacks to me though. + + "rules": [ + { + "action": "allow" + }, + { + "action": "disallow", + "os": { + "name": "osx", + "version": "^10\\.5\\.\\d$" + } + } + ], + "incompatibilityReason": "There is a bug in LWJGL which makes it incompatible with OSX 10.5.8. Please go to New Profile and use 1.5.2 for now. Sorry!" +} +*/ + // QList rules; +}; \ No newline at end of file diff --git a/libmultimc/include/fullversionfactory.h b/libmultimc/include/fullversionfactory.h new file mode 100644 index 00000000..673a6a72 --- /dev/null +++ b/libmultimc/include/fullversionfactory.h @@ -0,0 +1,23 @@ +#pragma once +#include + +struct FullVersion; + +class FullVersionFactory +{ +public: + enum Error + { + AllOK, // all parsed OK + ParseError, // the file was corrupted somehow + UnsupportedVersion // the file was meant for a launcher version we don't support (yet) + } m_error; + QString error_string; + +public: + FullVersionFactory(); + QSharedPointer parse(QByteArray data); +private: + QSharedPointer parse4(QJsonObject root, QSharedPointer product); + QStringList legacyWhitelist; +}; \ No newline at end of file diff --git a/libmultimc/include/library.h b/libmultimc/include/library.h new file mode 100644 index 00000000..10ecb9f3 --- /dev/null +++ b/libmultimc/include/library.h @@ -0,0 +1,18 @@ +/* Copyright 2013 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 + + diff --git a/libmultimc/src/fullversion.cpp b/libmultimc/src/fullversion.cpp new file mode 100644 index 00000000..d66ce5bb --- /dev/null +++ b/libmultimc/src/fullversion.cpp @@ -0,0 +1,4 @@ +#include "fullversion.h" + + +// ECHO, echo, echo, .... \ No newline at end of file diff --git a/libmultimc/src/fullversionfactory.cpp b/libmultimc/src/fullversionfactory.cpp new file mode 100644 index 00000000..8873ee2d --- /dev/null +++ b/libmultimc/src/fullversionfactory.cpp @@ -0,0 +1,113 @@ +#include "fullversionfactory.h" +#include "fullversion.h" + +QSharedPointer FullVersionFactory::parse4(QJsonObject root, QSharedPointer product) +{ + product->id = root.value("id").toString(); + + // if it's on our legacy list, it's legacy + if(legacyWhitelist.contains(product->id)) + product->isLegacy = true; + + product->mainClass = root.value("mainClass").toString(); + auto procArgsValue = root.value("processArguments"); + if(procArgsValue.isString()) + { + product->processArguments = procArgsValue.toString(); + QString toCompare = product->processArguments.toLower(); + if(toCompare == "legacy") + { + product->minecraftArguments = " ${auth_player_name} ${auth_session}"; + product->isLegacy = true; + } + else if(toCompare == "username_session") + { + product->minecraftArguments = "--username ${auth_player_name} --session ${auth_session}"; + } + else if(toCompare == "username_session_version") + { + product->minecraftArguments = "--username ${auth_player_name} --session ${auth_session} --version ${profile_name}"; + } + } + + auto minecraftArgsValue = root.value("minecraftArguments"); + if(minecraftArgsValue.isString()) + { + product->minecraftArguments = minecraftArgsValue.toString(); + } + + product->releaseTime = root.value("releaseTime").toString(); + product->time = root.value("time").toString(); + + // Iterate through the list. + auto librariesValue = root.value("libraries"); + if(librariesValue.isArray()) + { + QJsonArray libList = root.value("libraries").toArray(); + for (auto lib : libList) + { + if (!lib.isObject()) + { + continue; + } + + QJsonObject libObj = lib.toObject(); + + QString crud = libObj.value("name").toString(); + product->libraries.append(crud); + + // TODO: improve! + /* + auto parts = crud.split(':'); + int zz = parts.size(); + */ + } + } + return product; +} + +QSharedPointer FullVersionFactory::parse(QByteArray data) +{ + QSharedPointer readVersion(new FullVersion()); + + QJsonParseError jsonError; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); + + if (jsonError.error != QJsonParseError::NoError) + { + error_string = QString( "Error reading version file :") + " " + jsonError.errorString(); + m_error = FullVersionFactory::ParseError; + return QSharedPointer(); + } + + if(!jsonDoc.isObject()) + { + error_string = "Error reading version file."; + m_error = FullVersionFactory::ParseError; + return QSharedPointer(); + } + QJsonObject root = jsonDoc.object(); + + readVersion->minimumLauncherVersion = root.value("minimumLauncherVersion").toDouble(); + switch(readVersion->minimumLauncherVersion) + { + case 1: + case 2: + case 3: + case 4: + return parse4(root, readVersion); + // ADD MORE HERE :D + default: + error_string = "Version file was for an unrecognized launcher version. RIP"; + m_error = FullVersionFactory::UnsupportedVersion; + return QSharedPointer(); + } +} + + +FullVersionFactory::FullVersionFactory() +{ + m_error = FullVersionFactory::AllOK; + legacyWhitelist.append("1.5.1"); + legacyWhitelist.append("1.5.2"); +} diff --git a/libmultimc/src/gameupdatetask.cpp b/libmultimc/src/gameupdatetask.cpp index b6c1f936..61880118 100644 --- a/libmultimc/src/gameupdatetask.cpp +++ b/libmultimc/src/gameupdatetask.cpp @@ -25,9 +25,12 @@ #include #include "minecraftversionlist.h" +#include "fullversionfactory.h" +#include #include "pathutils.h" + GameUpdateTask::GameUpdateTask(const LoginResponse &response, Instance *inst, QObject *parent) : Task(parent), m_response(response) { @@ -86,78 +89,20 @@ void GameUpdateTask::versionFileFinished() { JobPtr firstJob = specificVersionDownloadJob->getFirstJob(); auto DlJob = firstJob.dynamicCast(); - QJsonParseError jsonError; - QJsonDocument jsonDoc = QJsonDocument::fromJson(DlJob->m_data, &jsonError); + FullVersionFactory parser; + auto version = parser.parse(DlJob->m_data); - if (jsonError.error != QJsonParseError::NoError) + if(!version) { - error(QString( "Error reading version file :") + " " + jsonError.errorString()); + error(parser.error_string); exit(0); } - if(!jsonDoc.isObject()) - { - error("Error reading version file."); - exit(0); - } - QJsonObject root = jsonDoc.object(); - - /* - * FIXME: this distinction is pretty weak. The only other option - * is to have a list of all the legacy versions. - */ - QString args = root.value("processArguments").toString("legacy"); - if(args == "legacy") + if(version->isLegacy) { getLegacyJar(); return; } - /* - // Iterate through the list. - QJsonObject groupList = root.value("libraries").toObject(); - - for (QJsonObject::iterator iter = groupList.begin(); - iter != groupList.end(); iter++) - { - QString groupName = iter.key(); - - // If not an object, complain and skip to the next one. - if (!iter.value().isObject()) - { - qWarning(QString("Group '%1' in the group list should " - "be an object.").arg(groupName).toUtf8()); - continue; - } - - QJsonObject groupObj = iter.value().toObject(); - - // Create the group object. - InstanceGroup *group = new InstanceGroup(groupName, this); - groups.push_back(group); - - // If 'hidden' isn't a bool value, just assume it's false. - if (groupObj.value("hidden").isBool() && groupObj.value("hidden").toBool()) - { - group->setHidden(groupObj.value("hidden").toBool()); - } - - if (!groupObj.value("instances").isArray()) - { - qWarning(QString("Group '%1' in the group list is invalid. " - "It should contain an array " - "called 'instances'.").arg(groupName).toUtf8()); - continue; - } - - // Iterate through the list of instances in the group. - QJsonArray instancesArray = groupObj.value("instances").toArray(); - - for (QJsonArray::iterator iter2 = instancesArray.begin(); - iter2 != instancesArray.end(); iter2++) - { - groupMap[(*iter2).toString()] = groupName; - } - }*/ // save the version file in $instanceId/version.json and versions/$version/$version.json QString version_id = targetVersion->descriptor(); diff --git a/libmultimc/src/library.cpp b/libmultimc/src/library.cpp new file mode 100644 index 00000000..b0490616 --- /dev/null +++ b/libmultimc/src/library.cpp @@ -0,0 +1,18 @@ +/* Copyright 2013 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 "include/library.h" + +// default url for lib: https://s3.amazonaws.com/Minecraft.Download/libraries/