diff options
| author | Petr Mrázek <peterix@gmail.com> | 2017-11-11 01:38:31 +0100 |
|---|---|---|
| committer | Petr Mrázek <peterix@gmail.com> | 2017-12-03 01:22:34 +0100 |
| commit | 85ae710d407eb31527183d5f8bec0399eb209f33 (patch) | |
| tree | 23647a83506ad3bd052720fb40068240e9768481 /api/logic | |
| parent | 17c8f31a09da6bdfc4aa7f67b2ca86b791f2ba96 (diff) | |
| download | PrismLauncher-85ae710d407eb31527183d5f8bec0399eb209f33.tar.gz PrismLauncher-85ae710d407eb31527183d5f8bec0399eb209f33.tar.bz2 PrismLauncher-85ae710d407eb31527183d5f8bec0399eb209f33.zip | |
GH-2026 implement changes necessary to support 1.13 snapshots
Diffstat (limited to 'api/logic')
43 files changed, 2544 insertions, 992 deletions
diff --git a/api/logic/BaseInstance.cpp b/api/logic/BaseInstance.cpp index f52b2812..027b8f78 100644 --- a/api/logic/BaseInstance.cpp +++ b/api/logic/BaseInstance.cpp @@ -197,7 +197,7 @@ bool BaseInstance::canLaunch() const return (!hasVersionBroken() && !isRunning()); } -bool BaseInstance::reload() +bool BaseInstance::reloadSettings() { return m_settings->reload(); } diff --git a/api/logic/BaseInstance.h b/api/logic/BaseInstance.h index 26d4bc35..d0909031 100644 --- a/api/logic/BaseInstance.h +++ b/api/logic/BaseInstance.h @@ -30,6 +30,8 @@ #include "MessageLevel.h" #include "pathmatcher/IPathMatcher.h" +#include "net/Mode.h" + #include "multimc_logic_export.h" class QDir; @@ -148,7 +150,7 @@ public: virtual SettingsObjectPtr settings() const; /// returns a valid update task - virtual shared_qobject_ptr<Task> createUpdateTask() = 0; + virtual shared_qobject_ptr<Task> createUpdateTask(Net::Mode mode) = 0; /// returns a valid launcher (task container) virtual std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) = 0; @@ -224,7 +226,7 @@ public: virtual bool canEdit() const = 0; virtual bool canExport() const = 0; - virtual bool reload(); + bool reloadSettings(); /** * 'print' a verbose desription of the instance into a QStringList diff --git a/api/logic/CMakeLists.txt b/api/logic/CMakeLists.txt index 42bea98c..8a8ef495 100644 --- a/api/logic/CMakeLists.txt +++ b/api/logic/CMakeLists.txt @@ -239,8 +239,14 @@ set(MINECRAFT_SOURCES minecraft/MinecraftInstance.h minecraft/LaunchProfile.cpp minecraft/LaunchProfile.h + minecraft/Component.cpp + minecraft/Component.h minecraft/ComponentList.cpp minecraft/ComponentList.h + minecraft/ComponentUpdateTask.cpp + minecraft/ComponentUpdateTask.h + minecraft/MinecraftLoadAndCheck.h + minecraft/MinecraftLoadAndCheck.cpp minecraft/MinecraftUpdate.h minecraft/MinecraftUpdate.cpp minecraft/MojangVersionFormat.cpp @@ -260,8 +266,6 @@ set(MINECRAFT_SOURCES minecraft/MojangDownloadInfo.h minecraft/VersionFile.cpp minecraft/VersionFile.h - minecraft/ProfilePatch.cpp - minecraft/ProfilePatch.h minecraft/VersionFilterData.h minecraft/VersionFilterData.cpp minecraft/Mod.h diff --git a/api/logic/InstanceCreationTask.cpp b/api/logic/InstanceCreationTask.cpp index 21892f82..8a68815a 100644 --- a/api/logic/InstanceCreationTask.cpp +++ b/api/logic/InstanceCreationTask.cpp @@ -5,6 +5,7 @@ //FIXME: remove this #include "minecraft/MinecraftInstance.h" +#include "minecraft/ComponentList.h" InstanceCreationTask::InstanceCreationTask(SettingsObjectPtr settings, const QString & stagingPath, BaseVersionPtr version, const QString& instName, const QString& instIcon, const QString& instGroup) @@ -25,11 +26,13 @@ void InstanceCreationTask::executeTask() instanceSettings->suspendSave(); instanceSettings->registerSetting("InstanceType", "Legacy"); instanceSettings->set("InstanceType", "OneSix"); - auto inst = new MinecraftInstance(m_globalSettings, instanceSettings, m_stagingPath); - inst->setComponentVersion("net.minecraft", m_version->descriptor()); - inst->setName(m_instName); - inst->setIconKey(m_instIcon); - inst->init(); + MinecraftInstance inst(m_globalSettings, instanceSettings, m_stagingPath); + auto components = inst.getComponentList(); + components->buildingFromScratch(); + components->setComponentVersion("net.minecraft", m_version->descriptor(), true); + inst.setName(m_instName); + inst.setIconKey(m_instIcon); + inst.init(); instanceSettings->resumeSave(); } emitSucceeded(); diff --git a/api/logic/InstanceImportTask.cpp b/api/logic/InstanceImportTask.cpp index e2782cd8..80f68458 100644 --- a/api/logic/InstanceImportTask.cpp +++ b/api/logic/InstanceImportTask.cpp @@ -242,7 +242,9 @@ void InstanceImportTask::processFlame() mcVersion.remove(QRegExp("[.]+$")); qWarning() << "Mysterious trailing dots removed from Minecraft version while importing pack."; } - instance.setComponentVersion("net.minecraft", mcVersion); + auto components = instance.getComponentList(); + components->buildingFromScratch(); + components->setComponentVersion("net.minecraft", mcVersion, true); if(!forgeVersion.isEmpty()) { // FIXME: dirty, nasty, hack. Proper solution requires dependency resolution and knowledge of the metadata. @@ -257,7 +259,7 @@ void InstanceImportTask::processFlame() qWarning() << "Could not map recommended forge version for" << mcVersion; } } - instance.setComponentVersion("net.minecraftforge", forgeVersion); + components->setComponentVersion("net.minecraftforge", forgeVersion); } if (m_instIcon != "default") { diff --git a/api/logic/NullInstance.h b/api/logic/NullInstance.h index f689c5ab..27a8a251 100644 --- a/api/logic/NullInstance.h +++ b/api/logic/NullInstance.h @@ -29,7 +29,7 @@ public: { return nullptr; } - virtual shared_qobject_ptr< Task > createUpdateTask() override + virtual shared_qobject_ptr< Task > createUpdateTask(Net::Mode mode) override { return nullptr; } diff --git a/api/logic/ProblemProvider.h b/api/logic/ProblemProvider.h index 4040f4fa..978710f0 100644 --- a/api/logic/ProblemProvider.h +++ b/api/logic/ProblemProvider.h @@ -1,5 +1,7 @@ #pragma once +#include "multimc_logic_export.h" + enum class ProblemSeverity { None, @@ -13,7 +15,7 @@ struct PatchProblem QString m_description; }; -class ProblemProvider +class MULTIMC_LOGIC_EXPORT ProblemProvider { public: virtual ~ProblemProvider() {}; @@ -21,7 +23,7 @@ public: virtual ProblemSeverity getProblemSeverity() const = 0; }; -class ProblemContainer : public ProblemProvider +class MULTIMC_LOGIC_EXPORT ProblemContainer : public ProblemProvider { public: const QList<PatchProblem> getProblems() const override diff --git a/api/logic/launch/steps/Update.cpp b/api/logic/launch/steps/Update.cpp index f06c39eb..42ca3c67 100644 --- a/api/logic/launch/steps/Update.cpp +++ b/api/logic/launch/steps/Update.cpp @@ -23,7 +23,7 @@ void Update::executeTask() emitFailed(tr("Task aborted.")); return; } - m_updateTask.reset(m_parent->instance()->createUpdateTask()); + m_updateTask.reset(m_parent->instance()->createUpdateTask(m_mode)); if(m_updateTask) { connect(m_updateTask.get(), SIGNAL(finished()), this, SLOT(updateFinished())); diff --git a/api/logic/launch/steps/Update.h b/api/logic/launch/steps/Update.h index d855a1db..e9573bcd 100644 --- a/api/logic/launch/steps/Update.h +++ b/api/logic/launch/steps/Update.h @@ -19,13 +19,14 @@ #include <QObjectPtr.h> #include <LoggedProcess.h> #include <java/JavaChecker.h> +#include <net/Mode.h> // FIXME: stupid. should be defined by the instance type? or even completely abstracted away... class Update: public LaunchStep { Q_OBJECT public: - explicit Update(LaunchTask *parent):LaunchStep(parent) {}; + explicit Update(LaunchTask *parent, Net::Mode mode):LaunchStep(parent), m_mode(mode) {}; virtual ~Update() {}; void executeTask() override; @@ -40,4 +41,5 @@ private slots: private: shared_qobject_ptr<Task> m_updateTask; bool m_aborted = false; + Net::Mode m_mode = Net::Mode::Offline; }; diff --git a/api/logic/meta/BaseEntity.cpp b/api/logic/meta/BaseEntity.cpp index 6bac71ee..7cf327be 100644 --- a/api/logic/meta/BaseEntity.cpp +++ b/api/logic/meta/BaseEntity.cpp @@ -99,7 +99,7 @@ bool Meta::BaseEntity::loadLocalFile() } } -void Meta::BaseEntity::load() +void Meta::BaseEntity::load(Net::Mode loadType) { // load local file if nothing is loaded yet if(!isLoaded()) @@ -110,7 +110,7 @@ void Meta::BaseEntity::load() } } // if we need remote update, run the update task - if(!shouldStartRemoteUpdate()) + if(loadType == Net::Mode::Offline || !shouldStartRemoteUpdate()) { return; } diff --git a/api/logic/meta/BaseEntity.h b/api/logic/meta/BaseEntity.h index 4483beab..4c74b1a7 100644 --- a/api/logic/meta/BaseEntity.h +++ b/api/logic/meta/BaseEntity.h @@ -20,6 +20,7 @@ #include "QObjectPtr.h" #include "multimc_logic_export.h" +#include "net/Mode.h" class Task; namespace Meta @@ -54,7 +55,7 @@ public: bool isLoaded() const; bool shouldStartRemoteUpdate() const; - void load(); + void load(Net::Mode loadType); shared_qobject_ptr<Task> getCurrentTask(); protected: /* methods */ diff --git a/api/logic/meta/JsonFormat.cpp b/api/logic/meta/JsonFormat.cpp index d13c89df..2c313478 100644 --- a/api/logic/meta/JsonFormat.cpp +++ b/api/logic/meta/JsonFormat.cpp @@ -51,18 +51,11 @@ static VersionPtr parseCommonVersion(const QString &uid, const QJsonObject &obj) version->setType(ensureString(obj, "type", QString())); version->setParentUid(ensureString(obj, "parentUid", QString())); version->setRecommended(ensureBoolean(obj, QString("recommended"), false)); - if(obj.contains("requires")) - { - QHash<QString, QString> requires; - auto reqobj = requireObject(obj, "requires"); - auto iter = reqobj.begin(); - while(iter != reqobj.end()) - { - requires[iter.key()] = requireString(iter.value()); - iter++; - } - version->setRequires(requires); - } + version->setVolatile(ensureBoolean(obj, QString("volatile"), false)); + RequireSet requires, conflicts; + parseRequires(obj, &requires, "requires"); + parseRequires(obj, &conflicts, "conflicts"); + version->setRequires(requires, conflicts); return version; } @@ -145,4 +138,53 @@ void parseVersion(const QJsonObject &obj, Version *ptr) throw ParseException(QObject::tr("Unknown formatVersion: %1").arg(version)); } } + +/* +[ +{"uid":"foo", "equals":"version"} +] +*/ +void parseRequires(const QJsonObject& obj, RequireSet* ptr, const char * keyName) +{ + if(obj.contains(keyName)) + { + QSet<QString> requires; + auto reqArray = requireArray(obj, keyName); + auto iter = reqArray.begin(); + while(iter != reqArray.end()) + { + auto reqObject = requireObject(*iter); + auto uid = requireString(reqObject, "uid"); + auto equals = ensureString(reqObject, "equals", QString()); + auto suggests = ensureString(reqObject, "suggests", QString()); + ptr->insert({uid, equals, suggests}); + iter++; + } + } } +void serializeRequires(QJsonObject& obj, RequireSet* ptr, const char * keyName) +{ + if(!ptr || ptr->empty()) + { + return; + } + QJsonArray arrOut; + for(auto &iter: *ptr) + { + QJsonObject reqOut; + reqOut.insert("uid", iter.uid); + if(!iter.equalsVersion.isEmpty()) + { + reqOut.insert("equals", iter.equalsVersion); + } + if(!iter.suggests.isEmpty()) + { + reqOut.insert("suggests", iter.suggests); + } + arrOut.append(reqOut); + } + obj.insert(keyName, arrOut); +} + +} + diff --git a/api/logic/meta/JsonFormat.h b/api/logic/meta/JsonFormat.h index aaed07fc..9b9dcd91 100644 --- a/api/logic/meta/JsonFormat.h +++ b/api/logic/meta/JsonFormat.h @@ -20,6 +20,7 @@ #include "Exception.h" #include "meta/BaseEntity.h" +#include <set> namespace Meta { @@ -32,9 +33,41 @@ class ParseException : public Exception public: using Exception::Exception; }; +struct Require +{ + bool operator==(const Require & rhs) const + { + return uid == rhs.uid; + } + bool operator<(const Require & rhs) const + { + return uid < rhs.uid; + } + bool deepEquals(const Require & rhs) const + { + return uid == rhs.uid + && equalsVersion == rhs.equalsVersion + && suggests == rhs.suggests; + } + QString uid; + QString equalsVersion; + QString suggests; +}; + +inline Q_DECL_PURE_FUNCTION uint qHash(const Require &key, uint seed = 0) Q_DECL_NOTHROW +{ + return qHash(key.uid, seed); +} + +using RequireSet = std::set<Require>; void parseIndex(const QJsonObject &obj, Index *ptr); void parseVersion(const QJsonObject &obj, Version *ptr); void parseVersionList(const QJsonObject &obj, VersionList *ptr); +// FIXME: this has a different shape than the others...FIX IT!? +void parseRequires(const QJsonObject &obj, RequireSet * ptr, const char * keyName = "requires"); +void serializeRequires(QJsonObject & objOut, RequireSet* ptr, const char * keyName = "requires"); } + +Q_DECLARE_METATYPE(std::set<Meta::Require>);
\ No newline at end of file diff --git a/api/logic/meta/Version.cpp b/api/logic/meta/Version.cpp index bf739157..d82878a1 100644 --- a/api/logic/meta/Version.cpp +++ b/api/logic/meta/Version.cpp @@ -74,12 +74,20 @@ void Meta::Version::merge(const std::shared_ptr<BaseEntity> &other) } if (m_requires != version->m_requires) { - setRequires(version->m_requires); + m_requires = version->m_requires; + } + if (m_conflicts != version->m_conflicts) + { + m_conflicts = version->m_conflicts; } if (m_parentUid != version->m_parentUid) { setParentUid(version->m_parentUid); } + if(m_volatile != version->m_volatile) + { + setVolatile(version->m_volatile); + } if(version->m_data) { setData(version->m_data); @@ -109,12 +117,19 @@ void Meta::Version::setTime(const qint64 time) emit timeChanged(); } -void Meta::Version::setRequires(const QHash<QString, QString> &requires) +void Meta::Version::setRequires(const Meta::RequireSet &requires, const Meta::RequireSet &conflicts) { m_requires = requires; + m_conflicts = conflicts; emit requiresChanged(); } +void Meta::Version::setVolatile(bool volatile_) +{ + m_volatile = volatile_; +} + + void Meta::Version::setData(const VersionFilePtr &data) { m_data = data; diff --git a/api/logic/meta/Version.h b/api/logic/meta/Version.h index 2f92ee9f..61f253c6 100644 --- a/api/logic/meta/Version.h +++ b/api/logic/meta/Version.h @@ -28,6 +28,8 @@ #include "multimc_logic_export.h" +#include "JsonFormat.h" + namespace Meta { using VersionPtr = std::shared_ptr<class Version>; @@ -65,7 +67,7 @@ public: /* con/des */ { return m_time; } - const QHash<QString, QString> &requires() const + const Meta::RequireSet &requires() const { return m_requires; } @@ -77,6 +79,10 @@ public: /* con/des */ { return m_recommended; } + bool isLoaded() const + { + return m_data != nullptr; + } void merge(const std::shared_ptr<BaseEntity> &other) override; void parse(const QJsonObject &obj) override; @@ -87,7 +93,8 @@ public: // for usage by format parsers only void setParentUid(const QString &parentUid); void setType(const QString &type); void setTime(const qint64 time); - void setRequires(const QHash<QString, QString> &requires); + void setRequires(const Meta::RequireSet &requires, const Meta::RequireSet &conflicts); + void setVolatile(bool volatile_); void setRecommended(bool recommended); void setProvidesRecommendations(); void setData(const VersionFilePtr &data); @@ -106,7 +113,9 @@ private: QString m_version; QString m_type; qint64 m_time = 0; - QHash<QString, QString> m_requires; + Meta::RequireSet m_requires; + Meta::RequireSet m_conflicts; + bool m_volatile = false; VersionFilePtr m_data; }; } diff --git a/api/logic/meta/VersionList.cpp b/api/logic/meta/VersionList.cpp index 4da0fb76..8910c4d7 100644 --- a/api/logic/meta/VersionList.cpp +++ b/api/logic/meta/VersionList.cpp @@ -30,7 +30,7 @@ VersionList::VersionList(const QString &uid, QObject *parent) shared_qobject_ptr<Task> VersionList::getLoadTask() { - load(); + load(Net::Mode::Online); return getCurrentTask(); } @@ -81,10 +81,13 @@ QVariant VersionList::data(const QModelIndex &index, int role) const return QVariant(); } auto & reqs = version->requires(); - auto iter = reqs.find(parentUid); + auto iter = std::find_if(reqs.begin(), reqs.end(), [&parentUid](const Require & req) + { + return req.uid == parentUid; + }); if (iter != reqs.end()) { - return iter.value(); + return (*iter).equalsVersion; } } case TypeRole: return version->type(); @@ -159,6 +162,7 @@ void VersionList::setVersions(const QVector<VersionPtr> &versions) setupAddedVersion(i, m_versions.at(i)); } + // FIXME: this is dumb, we have 'recommended' as part of the metadata already... auto recommendedIt = std::find_if(m_versions.constBegin(), m_versions.constEnd(), [](const VersionPtr &ptr) { return ptr->type() == "release"; }); m_recommended = recommendedIt == m_versions.constEnd() ? nullptr : *recommendedIt; endResetModel(); @@ -169,6 +173,22 @@ void VersionList::parse(const QJsonObject& obj) parseVersionList(obj, this); } +// FIXME: this is dumb, we have 'recommended' as part of the metadata already... +static const Meta::VersionPtr &getBetterVersion(const Meta::VersionPtr &a, const Meta::VersionPtr &b) +{ + if(!a) + return b; + if(!b) + return a; + if(a->type() == b->type()) + { + // newer of same type wins + return (a->rawTime() > b->rawTime() ? a : b); + } + // 'release' type wins + return (a->type() == "release" ? a : b); +} + void VersionList::merge(const BaseEntity::Ptr &other) { const VersionListPtr list = std::dynamic_pointer_cast<VersionList>(other); @@ -199,10 +219,7 @@ void VersionList::merge(const BaseEntity::Ptr &other) // connect it. setupAddedVersion(m_versions.size(), version); m_versions.append(version); - if (!m_recommended || (version->type() == "release" && version->rawTime() > m_recommended->rawTime())) - { - m_recommended = version; - } + m_recommended = getBetterVersion(m_recommended, version); } endResetModel(); } diff --git a/api/logic/minecraft/Component.cpp b/api/logic/minecraft/Component.cpp new file mode 100644 index 00000000..db523142 --- /dev/null +++ b/api/logic/minecraft/Component.cpp @@ -0,0 +1,408 @@ +#include <meta/VersionList.h> +#include <meta/Index.h> +#include <Env.h> +#include "Component.h" + +#include "meta/Version.h" +#include "VersionFile.h" +#include "minecraft/ComponentList.h" +#include <FileSystem.h> +#include <QSaveFile> +#include "OneSixVersionFormat.h" +#include <assert.h> + +Component::Component(ComponentList * parent, const QString& uid) +{ + assert(parent); + m_parent = parent; + + m_uid = uid; +} + +Component::Component(ComponentList * parent, std::shared_ptr<Meta::Version> version) +{ + assert(parent); + m_parent = parent; + + m_metaVersion = version; + m_uid = version->uid(); + m_version = m_cachedVersion = version->version(); + m_cachedName = version->name(); + m_loaded = version->isLoaded(); +} + +Component::Component(ComponentList * parent, const QString& uid, std::shared_ptr<VersionFile> file) +{ + assert(parent); + m_parent = parent; + + m_file = file; + m_uid = uid; + m_cachedVersion = m_file->version; + m_cachedName = m_file->name; + m_loaded = true; +} + +std::shared_ptr<Meta::Version> Component::getMeta() +{ + return m_metaVersion; +} + +void Component::applyTo(LaunchProfile* profile) +{ + auto vfile = getVersionFile(); + if(vfile) + { + vfile->applyTo(profile); + } + else + { + profile->applyProblemSeverity(getProblemSeverity()); + } +} + +std::shared_ptr<class VersionFile> Component::getVersionFile() const +{ + if(m_metaVersion) + { + if(!m_metaVersion->isLoaded()) + { + m_metaVersion->load(Net::Mode::Online); + } + return m_metaVersion->data(); + } + else + { + return m_file; + } +} + +std::shared_ptr<class Meta::VersionList> Component::getVersionList() const +{ + // FIXME: what if the metadata index isn't loaded yet? + if(ENV.metadataIndex()->hasUid(m_uid)) + { + return ENV.metadataIndex()->get(m_uid); + } + return nullptr; +} + +int Component::getOrder() +{ + if(m_orderOverride) + return m_order; + + auto vfile = getVersionFile(); + if(vfile) + { + return vfile->order; + } + return 0; +} +void Component::setOrder(int order) +{ + m_orderOverride = true; + m_order = order; +} +QString Component::getID() +{ + return m_uid; +} +QString Component::getName() +{ + if (!m_cachedName.isEmpty()) + return m_cachedName; + return m_uid; +} +QString Component::getVersion() +{ + return m_cachedVersion; +} +QString Component::getFilename() +{ + return m_parent->patchFilePathForUid(m_uid); +} +QDateTime Component::getReleaseDateTime() +{ + if(m_metaVersion) + { + return m_metaVersion->time(); + } + auto vfile = getVersionFile(); + if(vfile) + { + return vfile->releaseTime; + } + // FIXME: fake + return QDateTime::currentDateTime(); +} + +bool Component::isCustom() +{ + return m_file != nullptr; +}; + +bool Component::isCustomizable() +{ + if(m_metaVersion) + { + if(getVersionFile()) + { + return true; + } |
