diff options
| author | Petr Mrázek <peterix@gmail.com> | 2014-05-08 21:20:10 +0200 |
|---|---|---|
| committer | Petr Mrázek <peterix@gmail.com> | 2014-06-09 01:38:30 +0200 |
| commit | 8a3a0f5a529a95c7511436051b63887dff158c50 (patch) | |
| tree | 0162e0d6a37cd5a5b3aa5facf6ba6561e33f60bf /logic/minecraft | |
| parent | 69a9ca39ad0685663092a4455de3865715f0122e (diff) | |
| download | PrismLauncher-8a3a0f5a529a95c7511436051b63887dff158c50.tar.gz PrismLauncher-8a3a0f5a529a95c7511436051b63887dff158c50.tar.bz2 PrismLauncher-8a3a0f5a529a95c7511436051b63887dff158c50.zip | |
Reorganize logic code.
Diffstat (limited to 'logic/minecraft')
| -rw-r--r-- | logic/minecraft/MinecraftVersion.h | 92 | ||||
| -rw-r--r-- | logic/minecraft/MinecraftVersionList.cpp | 330 | ||||
| -rw-r--r-- | logic/minecraft/MinecraftVersionList.h | 76 | ||||
| -rw-r--r-- | logic/minecraft/OneSixLibrary.cpp | 274 | ||||
| -rw-r--r-- | logic/minecraft/OneSixLibrary.h | 148 | ||||
| -rw-r--r-- | logic/minecraft/OneSixRule.cpp | 89 | ||||
| -rw-r--r-- | logic/minecraft/OneSixRule.h | 98 | ||||
| -rw-r--r-- | logic/minecraft/OneSixVersionBuilder.cpp | 249 | ||||
| -rw-r--r-- | logic/minecraft/OneSixVersionBuilder.h | 46 | ||||
| -rw-r--r-- | logic/minecraft/OpSys.cpp | 42 | ||||
| -rw-r--r-- | logic/minecraft/OpSys.h | 37 | ||||
| -rw-r--r-- | logic/minecraft/VersionFile.cpp | 635 | ||||
| -rw-r--r-- | logic/minecraft/VersionFile.h | 145 | ||||
| -rw-r--r-- | logic/minecraft/VersionFinal.cpp | 429 | ||||
| -rw-r--r-- | logic/minecraft/VersionFinal.h | 172 |
15 files changed, 2862 insertions, 0 deletions
diff --git a/logic/minecraft/MinecraftVersion.h b/logic/minecraft/MinecraftVersion.h new file mode 100644 index 00000000..3be25912 --- /dev/null +++ b/logic/minecraft/MinecraftVersion.h @@ -0,0 +1,92 @@ +/* Copyright 2013 Andrew Okin + * + * 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 "logic/BaseVersion.h" +#include <QStringList> +#include <QSet> + +struct MinecraftVersion : public BaseVersion +{ + /// The version's timestamp - this is primarily used for sorting versions in a list. + qint64 timestamp; + + /// The URL that this version will be downloaded from. maybe. + QString download_url; + + /// is this the latest version? + bool is_latest = false; + + /// is this a snapshot? + bool is_snapshot = false; + + /// is this a built-in version that comes with MultiMC? + bool is_builtin = false; + + /// the human readable version name + QString m_name; + + /// the version ID. + QString m_descriptor; + + /// version traits. generally launcher business... + QSet<QString> m_traits; + + /// The main class this version uses (if any, can be empty). + QString m_mainClass; + + /// The applet class this version uses (if any, can be empty). + QString m_appletClass; + + bool usesLegacyLauncher() + { + return m_traits.contains("legacyLaunch") || m_traits.contains("aplhaLaunch"); + } + + virtual QString descriptor() override + { + return m_descriptor; + } + + virtual QString name() override + { + return m_name; + } + + virtual QString typeString() const override + { + if (is_latest && is_snapshot) + { + return QObject::tr("Latest snapshot"); + } + else if(is_latest) + { + return QObject::tr("Latest release"); + } + else if(is_snapshot) + { + return QObject::tr("Snapshot"); + } + else if(is_builtin) + { + return QObject::tr("Museum piece"); + } + else + { + return QObject::tr("Regular release"); + } + } +}; diff --git a/logic/minecraft/MinecraftVersionList.cpp b/logic/minecraft/MinecraftVersionList.cpp new file mode 100644 index 00000000..cdf5fa77 --- /dev/null +++ b/logic/minecraft/MinecraftVersionList.cpp @@ -0,0 +1,330 @@ +/* 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 "MinecraftVersionList.h" +#include "MultiMC.h" +#include "logic/net/URLConstants.h" +#include <logic/MMCJson.h> + +#include <QtXml> + +#include <QJsonDocument> +#include <QJsonObject> +#include <QJsonArray> +#include <QJsonValue> +#include <QJsonParseError> + +#include <QtAlgorithms> + +#include <QtNetwork> + +inline QDateTime timeFromS3Time(QString str) +{ + return QDateTime::fromString(str, Qt::ISODate); +} + +MinecraftVersionList::MinecraftVersionList(QObject *parent) : BaseVersionList(parent) +{ + loadBuiltinList(); +} + +Task *MinecraftVersionList::getLoadTask() +{ + return new MCVListLoadTask(this); +} + +bool MinecraftVersionList::isLoaded() +{ + return m_loaded; +} + +const BaseVersionPtr MinecraftVersionList::at(int i) const +{ + return m_vlist.at(i); +} + +int MinecraftVersionList::count() const +{ + return m_vlist.count(); +} + +static bool cmpVersions(BaseVersionPtr first, BaseVersionPtr second) +{ + auto left = std::dynamic_pointer_cast<MinecraftVersion>(first); + auto right = std::dynamic_pointer_cast<MinecraftVersion>(second); + return left->timestamp > right->timestamp; +} + +void MinecraftVersionList::sortInternal() +{ + qSort(m_vlist.begin(), m_vlist.end(), cmpVersions); +} + +void MinecraftVersionList::loadBuiltinList() +{ + // grab the version list data from internal resources. + QResource versionList(":/versions/minecraft.json"); + QFile filez(versionList.absoluteFilePath()); + filez.open(QIODevice::ReadOnly); + auto data = filez.readAll(); + + // parse the data as json + QJsonParseError jsonError; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); + QJsonObject root = jsonDoc.object(); + + // parse all the versions + for (const auto version : MMCJson::ensureArray(root.value("versions"))) + { + QJsonObject versionObj = version.toObject(); + QString versionID = versionObj.value("id").toString(""); + QString versionTimeStr = versionObj.value("releaseTime").toString(""); + QString versionTypeStr = versionObj.value("type").toString(""); + QSet<QString> traits; + if (versionObj.contains("+traits")) + { + for (auto traitVal : MMCJson::ensureArray(versionObj.value("+traits"))) + { + traits.insert(MMCJson::ensureString(traitVal)); + } + } + if (versionID.isEmpty() || versionTimeStr.isEmpty() || versionTypeStr.isEmpty()) + { + // FIXME: log this somewhere + continue; + } + // Parse the timestamp. + QDateTime versionTime = timeFromS3Time(versionTimeStr); + if (!versionTime.isValid()) + { + // FIXME: log this somewhere + continue; + } + // Get the download URL. + QString dlUrl = "http://" + URLConstants::AWS_DOWNLOAD_VERSIONS + versionID + "/"; + + // main class and applet class + QString mainClass = versionObj.value("type").toString(""); + QString appletClass = versionObj.value("type").toString(""); + + // Now, we construct the version object and add it to the list. + std::shared_ptr<MinecraftVersion> mcVersion(new MinecraftVersion()); + mcVersion->m_name = mcVersion->m_descriptor = versionID; + mcVersion->timestamp = versionTime.toMSecsSinceEpoch(); + mcVersion->download_url = dlUrl; + mcVersion->is_builtin = true; + mcVersion->m_appletClass = appletClass; + mcVersion->m_mainClass = mainClass; + mcVersion->m_traits = traits; + m_vlist.append(mcVersion); + } +} + +void MinecraftVersionList::sort() +{ + beginResetModel(); + sortInternal(); + endResetModel(); +} + +BaseVersionPtr MinecraftVersionList::getLatestStable() const +{ + for (int i = 0; i < m_vlist.length(); i++) + { + auto ver = std::dynamic_pointer_cast<MinecraftVersion>(m_vlist.at(i)); + if (ver->is_latest && !ver->is_snapshot) + { + return m_vlist.at(i); + } + } + return BaseVersionPtr(); +} + +void MinecraftVersionList::updateListData(QList<BaseVersionPtr> versions) +{ + beginResetModel(); + for (auto version : versions) + { + auto descr = version->descriptor(); + for (auto builtin_v : m_vlist) + { + if (descr == builtin_v->descriptor()) + { + goto SKIP_THIS_ONE; + } + } + m_vlist.append(version); + SKIP_THIS_ONE: + { + } + } + m_loaded = true; + sortInternal(); + endResetModel(); +} + +inline QDomElement getDomElementByTagName(QDomElement parent, QString tagname) +{ + QDomNodeList elementList = parent.elementsByTagName(tagname); + if (elementList.count()) + return elementList.at(0).toElement(); + else + return QDomElement(); +} + +MCVListLoadTask::MCVListLoadTask(MinecraftVersionList *vlist) +{ + m_list = vlist; + m_currentStable = NULL; + vlistReply = nullptr; +} + +MCVListLoadTask::~MCVListLoadTask() +{ +} + +void MCVListLoadTask::executeTask() +{ + setStatus(tr("Loading instance version list...")); + auto worker = MMC->qnam(); + vlistReply = worker->get(QNetworkRequest( + QUrl("http://" + URLConstants::AWS_DOWNLOAD_VERSIONS + "versions.json"))); + connect(vlistReply, SIGNAL(finished()), this, SLOT(list_downloaded())); +} + +void MCVListLoadTask::list_downloaded() +{ + if (vlistReply->error() != QNetworkReply::NoError) + { + vlistReply->deleteLater(); + emitFailed("Failed to load Minecraft main version list" + vlistReply->errorString()); + return; + } + + auto foo = vlistReply->readAll(); + QJsonParseError jsonError; + QLOG_INFO() << foo; + QJsonDocument jsonDoc = QJsonDocument::fromJson(foo, &jsonError); + vlistReply->deleteLater(); + + 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; + } + + QJsonObject root = jsonDoc.object(); + + QString latestReleaseID = "INVALID"; + QString latestSnapshotID = "INVALID"; + try + { + QJsonObject latest = MMCJson::ensureObject(root.value("latest")); + latestReleaseID = MMCJson::ensureString(latest.value("release")); + latestSnapshotID = MMCJson::ensureString(latest.value("snapshot")); + } + catch (MMCError &err) + { + QLOG_ERROR() + << tr("Error parsing version list JSON: couldn't determine latest versions"); + } + + // Now, get the array of versions. + if (!root.value("versions").isArray()) + { + emitFailed( + "Error parsing version list JSON: version list object is missing 'versions' array"); + return; + } + QJsonArray versions = root.value("versions").toArray(); + + QList<BaseVersionPtr> tempList; + for (auto version : versions) + { + bool is_snapshot = false; + bool is_latest = false; + + // Load the version info. + if (!version.isObject()) + { + // FIXME: log this somewhere + continue; + } + QJsonObject versionObj = version.toObject(); + QString versionID = versionObj.value("id").toString(""); + QString versionTimeStr = versionObj.value("releaseTime").toString(""); + QString versionTypeStr = versionObj.value("type").toString(""); + if (versionID.isEmpty() || versionTimeStr.isEmpty() || versionTypeStr.isEmpty()) + { + // FIXME: log this somewhere + continue; + } + + // Parse the timestamp. + QDateTime versionTime = timeFromS3Time(versionTimeStr); + if (!versionTime.isValid()) + { + // FIXME: log this somewhere + continue; + } + // OneSix or Legacy. use filter to determine type + if (versionTypeStr == "release") + { + is_latest = (versionID == latestReleaseID); + is_snapshot = false; + } + else if (versionTypeStr == "snapshot") // It's a snapshot... yay + { + is_latest = (versionID == latestSnapshotID); + is_snapshot = true; + } + else if (versionTypeStr == "old_alpha") + { + is_latest = false; + is_snapshot = false; + } + else if (versionTypeStr == "old_beta") + { + is_latest = false; + is_snapshot = false; + } + else + { + // FIXME: log this somewhere + continue; + } + // Get the download URL. + QString dlUrl = "http://" + URLConstants::AWS_DOWNLOAD_VERSIONS + versionID + "/"; + + // Now, we construct the version object and add it to the list. + std::shared_ptr<MinecraftVersion> mcVersion(new MinecraftVersion()); + mcVersion->m_name = mcVersion->m_descriptor = versionID; + mcVersion->timestamp = versionTime.toMSecsSinceEpoch(); + mcVersion->download_url = dlUrl; + mcVersion->is_latest = is_latest; + mcVersion->is_snapshot = is_snapshot; + tempList.append(mcVersion); + } + m_list->updateListData(tempList); + + emitSucceeded(); + return; +} diff --git a/logic/minecraft/MinecraftVersionList.h b/logic/minecraft/MinecraftVersionList.h new file mode 100644 index 00000000..18b9b21e --- /dev/null +++ b/logic/minecraft/MinecraftVersionList.h @@ -0,0 +1,76 @@ +/* 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 + +#include <QObject> +#include <QList> +#include <QSet> + +#include "logic/BaseVersionList.h" +#include "logic/tasks/Task.h" +#include "logic/minecraft/MinecraftVersion.h" + +class MCVListLoadTask; +class QNetworkReply; + +class MinecraftVersionList : public BaseVersionList +{ + Q_OBJECT +private: + void sortInternal(); + void loadBuiltinList(); +public: + friend class MCVListLoadTask; + + explicit MinecraftVersionList(QObject *parent = 0); + + virtual Task *getLoadTask(); + virtual bool isLoaded(); + virtual const BaseVersionPtr at(int i) const; + virtual int count() const; + virtual void sort(); + + virtual BaseVersionPtr getLatestStable() const; + +protected: + QList<BaseVersionPtr> m_vlist; + + bool m_loaded = false; + +protected +slots: + virtual void updateListData(QList<BaseVersionPtr> versions); +}; + +class MCVListLoadTask : public Task +{ + Q_OBJECT + +public: + explicit MCVListLoadTask(MinecraftVersionList *vlist); + ~MCVListLoadTask(); + + virtual void executeTask(); + +protected +slots: + void list_downloaded(); + +protected: + QNetworkReply *vlistReply; + MinecraftVersionList *m_list; + MinecraftVersion *m_currentStable; +}; diff --git a/logic/minecraft/OneSixLibrary.cpp b/logic/minecraft/OneSixLibrary.cpp new file mode 100644 index 00000000..45fa169e --- /dev/null +++ b/logic/minecraft/OneSixLibrary.cpp @@ -0,0 +1,274 @@ +/* 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 <QJsonArray> + +#include "OneSixLibrary.h" +#include "OneSixRule.h" +#include "OpSys.h" +#include "logic/net/URLConstants.h" +#include <pathutils.h> +#include <JlCompress.h> +#include "logger/QsLog.h" + +void OneSixLibrary::finalize() +{ + QStringList parts = m_name.split(':'); + QString relative = parts[0]; + relative.replace('.', '/'); + relative += '/' + parts[1] + '/' + parts[2] + '/' + parts[1] + '-' + parts[2]; + + if (!m_is_native) + relative += ".jar"; + else + { + if (m_native_suffixes.contains(currentSystem)) + { + relative += "-" + m_native_suffixes[currentSystem] + ".jar"; + } + else + { + // really, bad. + relative += ".jar"; + } + } + + m_decentname = parts[1]; + m_decentversion = minVersion = parts[2]; + m_storage_path = relative; + m_download_url = m_base_url + relative; + + if (m_rules.empty()) + { + m_is_active = true; + } + else + { + RuleAction result = Disallow; + for (auto rule : m_rules) + { + RuleAction temp = rule->apply(this); + if (temp != Defer) + result = temp; + } + m_is_active = (result == Allow); + } + if (m_is_native) + { + m_is_active = m_is_active && m_native_suffixes.contains(currentSystem); + m_decenttype = "Native"; + } + else + { + m_decenttype = "Java"; + } +} + +void OneSixLibrary::setName(const QString &name) +{ + m_name = name; +} +void OneSixLibrary::setBaseUrl(const QString &base_url) +{ + m_base_url = base_url; +} +void OneSixLibrary::setIsNative() +{ + m_is_native = true; +} +void OneSixLibrary::addNative(OpSys os, const QString &suffix) +{ + m_is_native = true; + m_native_suffixes[os] = suffix; +} +void OneSixLibrary::clearSuffixes() +{ + m_native_suffixes.clear(); +} +void OneSixLibrary::setRules(QList<std::shared_ptr<Rule>> rules) +{ + m_rules = rules; +} +bool OneSixLibrary::isActive() const +{ + return m_is_active; +} +bool OneSixLibrary::isNative() const +{ + return m_is_native; +} +QString OneSixLibrary::downloadUrl() const +{ + if (m_absolute_url.size()) + return m_absolute_url; + return m_download_url; +} +QString OneSixLibrary::storagePath() const +{ + return m_storage_path; +} + +void OneSixLibrary::setAbsoluteUrl(const QString &absolute_url) +{ + m_absolute_url = absolute_url; +} + +QString OneSixLibrary::absoluteUrl() const +{ + return m_absolute_url; +} + +void OneSixLibrary::setHint(const QString &hint) +{ + m_hint = hint; +} + +QString OneSixLibrary::hint() const +{ + return m_hint; +} + +QStringList OneSixLibrary::files() +{ + QStringList retval; + QString storage = storagePath(); + if (storage.contains("${arch}")) + { + QString cooked_storage = storage; + cooked_storage.replace("${arch}", "32"); + retval.append(cooked_storage); + cooked_storage = storage; + cooked_storage.replace("${arch}", "64"); + retval.append(cooked_storage); + } + else + retval.append(storage); + return retval; +} + +bool OneSixLibrary::filesExist(const QDir &base) +{ + auto libFiles = files(); + for(auto file: libFiles) + { + QFileInfo info(base, file); + QLOG_WARN() << info.absoluteFilePath() << "doesn't exist"; + if (!info.exists()) + return false; + } + return true; +} + +bool OneSixLibrary::extractTo(QString target_dir) +{ + QString storage = storagePath(); + if (storage.contains("${arch}")) + { + QString cooked_storage = storage; + cooked_storage.replace("${arch}", "32"); + QString origin = PathCombine("libraries", cooked_storage); + QString target_dir_cooked = PathCombine(target_dir, "32"); + if (!ensureFolderPathExists(target_dir_cooked)) + { + QLOG_ERROR() << "Couldn't create folder " + target_dir_cooked; + return false; + } + if (JlCompress::extractWithExceptions(origin, target_dir_cooked, extract_excludes) + .isEmpty()) + { + QLOG_ERROR() << "Couldn't extract " + origin; + return false; + } + cooked_storage = storage; + cooked_storage.replace("${arch}", "64"); + origin = PathCombine("libraries", cooked_storage); + target_dir_cooked = PathCombine(target_dir, "64"); + if (!ensureFolderPathExists(target_dir_cooked)) + { + QLOG_ERROR() << "Couldn't create folder " + target_dir_cooked; + return false; + } + if (JlCompress::extractWithExceptions(origin, target_dir_cooked, extract_excludes) + .isEmpty()) + { + QLOG_ERROR() << "Couldn't extract " + origin; + return false; + } + } + else + { + if (!ensureFolderPathExists(target_dir)) + { + QLOG_ERROR() << "Couldn't create folder " + target_dir; + return false; + } + QString path = PathCombine("libraries", storage); + if (JlCompress::extractWithExceptions(path, target_dir, extract_excludes).isEmpty()) + { + QLOG_ERROR() << "Couldn't extract " + path; + return false; + } + } + return true; +} + +QJsonObject OneSixLibrary::toJson() +{ + QJsonObject libRoot; + libRoot.insert("name", m_name); + if (m_absolute_url.size()) + libRoot.insert("MMC-absoluteUrl", m_absolute_url); + if (m_hint.size()) + libRoot.insert("MMC-hint", m_hint); + if (m_base_url != "http://" + URLConstants::AWS_DOWNLOAD_LIBRARIES && + m_base_url != "https://" + URLConstants::AWS_DOWNLOAD_LIBRARIES && + m_base_url != "https://" + URLConstants::LIBRARY_BASE && !m_base_url.isEmpty()) + { + libRoot.insert("url", m_base_url); + } + if (isNative() && m_native_suffixes.size()) + { + QJsonObject nativeList; + auto iter = m_native_suffixes.begin(); + while (iter != m_native_suffixes.end()) + { + nativeList.insert(OpSys_toString(iter.key()), iter.value()); + iter++; + } + libRoot.insert("natives", nativeList); + } + if (isNative() && extract_excludes.size()) + { + QJsonArray excludes; + QJsonObject extract; + for (auto exclude : extract_excludes) + { + excludes.append(exclude); + } + extract.insert("exclude", excludes); + libRoot.insert("extract", extract); + } + if (m_rules.size()) + { + QJsonArray allRules; + for (auto &rule : m_rules) + { + QJsonObject ruleObj = rule->toJson(); + allRules.append(ruleObj); + } + libRoot.insert("rules", allRules); + } + return libRoot; +} diff --git a/logic/minecraft/OneSixLibrary.h b/logic/minecraft/OneSixLibrary.h new file mode 100644 index 00000000..13df0606 --- /dev/null +++ b/logic/minecraft/OneSixLibrary.h @@ -0,0 +1,148 @@ +/* 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 + +#include <QString> +#include <QStringList> +#include <QMap> +#include <QJsonObject> +#include <QDir> +#include <memory> + +#include "logic/net/URLConstants.h" +#include "logic/minecraft/OpSys.h" + +class Rule; + +class OneSixLibrary; +typedef std::shared_ptr<OneSixLibrary> OneSixLibraryPtr; + +class OneSixLibrary +{ +private: + // basic values used internally (so far) + QString m_name; + QString m_base_url = "https://" + URLConstants::LIBRARY_BASE; + QList<std::shared_ptr<Rule>> m_rules; + + // custom values + /// absolute URL. takes precedence over m_download_path, if defined + QString m_absolute_url; + /// type hint - modifies how the library is treated + QString m_hint; + + // derived values used for real things + /// a decent name fit for display + QString m_decentname; + /// a decent version fit for display + QString m_decentversion; + /// a decent type fit for display + QString m_decenttype; + /// where to store the lib locally + QString m_storage_path; + /// where to download the lib from + QString m_download_url; + /// is this lib actually active on the current OS? + bool m_is_active = false; + /// is the library a native? + bool m_is_native = false; + /// native suffixes per OS + QMap<OpSys, QString> m_native_suffixes; + +public: + QStringList extract_excludes; + QString minVersion; + + enum DependType + { + Soft, + Hard + }; + DependType dependType; + +public: + /// Constructor + OneSixLibrary(const QString &name, const DependType type = Soft) + { + m_name = name; + dependType = type; + } + + /// Returns the raw name field + QString rawName() const + { + return m_name; + } + + QJsonObject toJson(); + + /** + * finalize the library, processing the input values into derived values and state + * + * This SHALL be called after all the values are parsed or after any further change. + */ + void finalize(); + + /// Set the library composite name + void setName(const QString &name); + /// get a decent-looking name + QString name() const + { + return m_decentname; + } + /// get a decent-looking version + QString version() const + { + return m_decentversion; + } + /// what kind of library is it? (for display) + QString type() const + { + return m_decenttype; + } + /// Set the url base for downloads + void setBaseUrl(const QString &base_url); + + /// Call this to mark the library as 'native' (it's a zip archive with DLLs) + void setIsNative(); + /// Attach a name suffix to the specified OS native + void addNative(OpSys os, const QString &suffix); + /// Clears all suffixes + void clearSuffixes(); + /// Set the load rules + void setRules(QList<std::shared_ptr<Rule>> rules); + + /// Returns true if the library should be loaded (or extracted, in case of natives) + bool isActive() const; + /// Returns true if the library is native + bool isNative() const; + /// Get the URL to download the library from + QString downloadUrl() const; + /// Get the relative path where the library should be saved + QString storagePath() const; + + /// set an absolute URL for the library. This is an MMC extension. + void setAbsoluteUrl(const QString &absolute_url); + QString absoluteUrl() const; + + /// set a hint about how to treat the library. This is an MMC extension. + void setHint(const QString &hint); + QString hint() const; + + bool extractTo(QString target_dir); + bool filesExist(const QDir &base); + QStringList files(); +}; diff --git a/logic/minecraft/OneSixRule.cpp b/logic/minecraft/OneSixRule.cpp new file mode 100644 index 00000000..d8d13b50 --- /dev/null +++ b/logic/minecraft/OneSixRule.cpp @@ -0,0 +1,89 @@ +/* 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 <QJsonObject> +#include <QJsonArray> + +#include "OneSixRule.h" + +QList<std::shared_ptr<Rule>> rulesFromJsonV4(const QJsonObject &objectWithRules) +{ + QList<std::shared_ptr<Rule>> rules; + auto rulesVal = objectWithRules.value("rules"); + if (!rulesVal.isArray()) + return rules; + + QJsonArray ruleList = rulesVal.toArray(); + for (auto ruleVal : ruleList) + { + std::shared_ptr<Rule> rule; + if (!ruleVal.isObject()) + continue; + auto ruleObj = ruleVal.toObject(); + auto actionVal = ruleObj.value("action"); + if (!actionVal.isString()) + continue; + auto action = RuleAction_fromString(actionVal.toString()); + if (action == Defer) + continue; + + auto osVal = ruleObj.value("os"); + if (!osVal.isObject()) + { + // add a new implicit action rule + rules.append(ImplicitRule::create(action)); + continue; + } + + auto osObj = osVal.toObject(); + auto osNameVal = osObj.value("name"); + if (!osNameVal.isString()) + continue; + OpSys requiredOs = OpSys_fromString(osNameVal.toString()); + QString versionRegex = osObj.value("version").toString(); + // add a new OS rule + rules.append(OsRule::create(action, requiredOs, versionRegex)); + } + return rules; +} + +QJsonObject ImplicitRule::toJson() +{ + QJsonObject ruleObj; + ruleObj.insert("action", m_result == Allow ? QString("allow") : QString("disallow")); + return ruleObj; +} + +QJsonObject OsRule::toJson() +{ + QJsonObject ruleObj; + ruleObj.insert("action", m_result == Allow ? QString("allow") : QString("disallow")); + QJsonObject osObj; + { + osObj.insert("name", OpSys_toString(m_system)); + osObj.insert("version", m_version_regexp); + } + ruleObj.insert("os", osObj); + return ruleObj; +} + +RuleAction RuleAction_fromString(QString name) +{ + if (name == "allow") + return Allow; + if (name == "disallow") + return Disallow; + return Defer; +} diff --git a/logic/minecraft/OneSixRule.h b/logic/minecraft/OneSixRule.h new file mode 100644 index 00000000..2c569b9f --- /dev/null +++ b/logic/minecraft/OneSixRule.h @@ -0,0 +1,98 @@ +/* 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. + * Se |
