diff options
Diffstat (limited to 'api/logic/minecraft/onesix')
-rw-r--r-- | api/logic/minecraft/onesix/OneSixInstance.cpp | 66 | ||||
-rw-r--r-- | api/logic/minecraft/onesix/OneSixInstance.h | 4 | ||||
-rw-r--r-- | api/logic/minecraft/onesix/OneSixProfileStrategy.cpp | 226 | ||||
-rw-r--r-- | api/logic/minecraft/onesix/OneSixUpdate.cpp | 49 | ||||
-rw-r--r-- | api/logic/minecraft/onesix/OneSixVersionFormat.cpp | 32 | ||||
-rw-r--r-- | api/logic/minecraft/onesix/update/LibrariesTask.cpp | 18 |
6 files changed, 225 insertions, 170 deletions
diff --git a/api/logic/minecraft/onesix/OneSixInstance.cpp b/api/logic/minecraft/onesix/OneSixInstance.cpp index b471ff3e..fd54f544 100644 --- a/api/logic/minecraft/onesix/OneSixInstance.cpp +++ b/api/logic/minecraft/onesix/OneSixInstance.cpp @@ -34,7 +34,15 @@ OneSixInstance::OneSixInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir) : MinecraftInstance(globalSettings, settings, rootDir) { + // set explicitly during instance creation m_settings->registerSetting({"IntendedVersion", "MinecraftVersion"}, ""); + + // defaults to the version we've been using for years (2.9.1) + m_settings->registerSetting("LWJGLVersion", "2.9.1"); + + // optionals + m_settings->registerSetting("ForgeVersion", ""); + m_settings->registerSetting("LiteloaderVersion", ""); } void OneSixInstance::init() @@ -275,6 +283,8 @@ QStringList OneSixInstance::verboseDescription(AuthSessionPtr session) printLibFile(file); } printLibFile(mainJarPath()); + out << ""; + out << "Native libraries:"; for(auto file: nativeJars) { printLibFile(file); @@ -480,7 +490,32 @@ std::shared_ptr<WorldList> OneSixInstance::worldList() const bool OneSixInstance::setIntendedVersionId(QString version) { - settings()->set("IntendedVersion", version); + return setComponentVersion("net.minecraft", version); +} + +QString OneSixInstance::intendedVersionId() const +{ + return getComponentVersion("net.minecraft"); +} + +bool OneSixInstance::setComponentVersion(const QString& uid, const QString& version) +{ + if(uid == "net.minecraft") + { + settings()->set("IntendedVersion", version); + } + else if (uid == "org.lwjgl") + { + settings()->set("LWJGLVersion", version); + } + else if (uid == "net.minecraftforge") + { + settings()->set("ForgeVersion", version); + } + else if (uid == "com.mumfrey.liteloader") + { + settings()->set("LiteloaderVersion", version); + } if(getMinecraftProfile()) { clearProfile(); @@ -489,6 +524,27 @@ bool OneSixInstance::setIntendedVersionId(QString version) return true; } +QString OneSixInstance::getComponentVersion(const QString& uid) const +{ + if(uid == "net.minecraft") + { + return settings()->get("IntendedVersion").toString(); + } + else if(uid == "org.lwjgl") + { + return settings()->get("LWJGLVersion").toString(); + } + else if(uid == "net.minecraftforge") + { + return settings()->get("ForgeVersion").toString(); + } + else if(uid == "com.mumfrey.liteloader") + { + return settings()->get("LiteloaderVersion").toString(); + } + return QString(); +} + QList< Mod > OneSixInstance::getJarMods() const { QList<Mod> mods; @@ -500,12 +556,6 @@ QList< Mod > OneSixInstance::getJarMods() const return mods; } - -QString OneSixInstance::intendedVersionId() const -{ - return settings()->get("IntendedVersion").toString(); -} - void OneSixInstance::setShouldUpdate(bool) { } @@ -523,7 +573,7 @@ QString OneSixInstance::currentVersionId() const void OneSixInstance::reloadProfile() { m_profile->reload(); - setVersionBroken(m_profile->getProblemSeverity() == ProblemSeverity::PROBLEM_ERROR); + setVersionBroken(m_profile->getProblemSeverity() == ProblemSeverity::Error); emit versionReloaded(); } diff --git a/api/logic/minecraft/onesix/OneSixInstance.h b/api/logic/minecraft/onesix/OneSixInstance.h index 72c05ad7..ec8c2597 100644 --- a/api/logic/minecraft/onesix/OneSixInstance.h +++ b/api/logic/minecraft/onesix/OneSixInstance.h @@ -59,9 +59,11 @@ public: virtual QString intendedVersionId() const override; virtual bool setIntendedVersionId(QString version) override; - virtual QString currentVersionId() const override; + QString getComponentVersion(const QString &uid) const; + bool setComponentVersion(const QString &uid, const QString &version); + virtual bool shouldUpdate() const override; virtual void setShouldUpdate(bool val) override; diff --git a/api/logic/minecraft/onesix/OneSixProfileStrategy.cpp b/api/logic/minecraft/onesix/OneSixProfileStrategy.cpp index 07c9f075..d3e137c7 100644 --- a/api/logic/minecraft/onesix/OneSixProfileStrategy.cpp +++ b/api/logic/minecraft/onesix/OneSixProfileStrategy.cpp @@ -3,7 +3,6 @@ #include "OneSixVersionFormat.h" #include "minecraft/VersionBuildError.h" -#include "minecraft/MinecraftVersionList.h" #include "Env.h" #include <FileSystem.h> @@ -11,6 +10,12 @@ #include <QUuid> #include <QJsonDocument> #include <QJsonArray> +#include <QSaveFile> +#include <QResource> +#include <meta/Index.h> +#include <meta/Version.h> + +#include <tuple> OneSixProfileStrategy::OneSixProfileStrategy(OneSixInstance* instance) { @@ -53,7 +58,7 @@ void OneSixProfileStrategy::upgradeDeprecatedFiles() } auto file = ProfileUtils::parseJsonFile(QFileInfo(sourceFile), false); ProfileUtils::removeLwjglFromPatch(file); - file->fileId = "net.minecraft"; + file->uid = "net.minecraft"; file->version = file->minecraftVersion; file->name = "Minecraft"; auto data = OneSixVersionFormat::versionFileToJson(file, false).toJson(); @@ -80,156 +85,128 @@ void OneSixProfileStrategy::upgradeDeprecatedFiles() void OneSixProfileStrategy::loadDefaultBuiltinPatches() { + auto addBuiltinPatch = [&](const QString &uid, const QString intendedVersion, int order) { - auto mcJson = FS::PathCombine(m_instance->instanceRoot(), "patches" , "net.minecraft.json"); + auto jsonFilePath = FS::PathCombine(m_instance->instanceRoot(), "patches" , uid + ".json"); // load up the base minecraft patch - ProfilePatchPtr minecraftPatch; - if(QFile::exists(mcJson)) + ProfilePatchPtr profilePatch; + if(QFile::exists(jsonFilePath)) { - auto file = ProfileUtils::parseJsonFile(QFileInfo(mcJson), false); + auto file = ProfileUtils::parseJsonFile(QFileInfo(jsonFilePath), false); if(file->version.isEmpty()) { - file->version = m_instance->intendedVersionId(); + file->version = intendedVersion; } - file->setVanilla(false); - file->setRevertible(true); - minecraftPatch = std::dynamic_pointer_cast<ProfilePatch>(file); + profilePatch = std::make_shared<ProfilePatch>(file, jsonFilePath); + profilePatch->setVanilla(false); + profilePatch->setRevertible(true); } else { - auto mcversion = ENV.getVersion("net.minecraft", m_instance->intendedVersionId()); - minecraftPatch = std::dynamic_pointer_cast<ProfilePatch>(mcversion); + auto metaVersion = ENV.metadataIndex()->get(uid, intendedVersion); + profilePatch = std::make_shared<ProfilePatch>(metaVersion); + profilePatch->setVanilla(true); } - if (!minecraftPatch) + if (!profilePatch) { - throw VersionIncomplete("net.minecraft"); + throw VersionIncomplete(uid); } - minecraftPatch->setOrder(-2); - profile->appendPatch(minecraftPatch); - } + profilePatch->setOrder(order); + profile->appendPatch(profilePatch); + }; + addBuiltinPatch("net.minecraft", m_instance->getComponentVersion("net.minecraft"), -2); + addBuiltinPatch("org.lwjgl", m_instance->getComponentVersion("org.lwjgl"), -1); +} +void OneSixProfileStrategy::loadUserPatches() +{ + // first, collect all patches (that are not builtins of OneSix) and load them + QMap<QString, ProfilePatchPtr> loadedPatches; + QDir patchesDir(FS::PathCombine(m_instance->instanceRoot(),"patches")); + for (auto info : patchesDir.entryInfoList(QStringList() << "*.json", QDir::Files)) { - auto lwjglJson = FS::PathCombine(m_instance->instanceRoot(), "patches" , "org.lwjgl.json"); - ProfilePatchPtr lwjglPatch; - if(QFile::exists(lwjglJson)) - { - auto file = ProfileUtils::parseJsonFile(QFileInfo(lwjglJson), false); - file->setVanilla(false); - file->setRevertible(true); - lwjglPatch = std::dynamic_pointer_cast<ProfilePatch>(file); - } - else + // parse the file + qDebug() << "Reading" << info.fileName(); + auto file = ProfileUtils::parseJsonFile(info, true); + // ignore builtins + if (file->uid == "net.minecraft") + continue; + if (file->uid == "org.lwjgl") + continue; + auto patch = std::make_shared<ProfilePatch>(file, info.filePath()); + patch->setRemovable(true); + patch->setMovable(true); + if(ENV.metadataIndex()->hasUid(file->uid)) { - // NOTE: this is obviously fake, is fixed in unstable. - QResource LWJGL(":/versions/LWJGL/2.9.1.json"); - auto lwjgl = ProfileUtils::parseJsonFile(LWJGL.absoluteFilePath(), false); - lwjgl->setVanilla(true); - lwjgl->setCustomizable(true); - lwjglPatch = std::dynamic_pointer_cast<ProfilePatch>(lwjgl); + // FIXME: requesting a uid/list creates it in the index... this allows reverting to possibly invalid versions... + patch->setRevertible(true); } - if (!lwjglPatch) + loadedPatches[file->uid] = patch; + } + // these are 'special'... if not already loaded from instance files, grab them from the metadata repo. + auto loadSpecial = [&](const QString & uid, int order) + { + auto patchVersion = m_instance->getComponentVersion(uid); + if(!patchVersion.isEmpty() && !loadedPatches.contains(uid)) { - throw VersionIncomplete("org.lwjgl"); + auto patch = std::make_shared<ProfilePatch>(ENV.metadataIndex()->get(uid, patchVersion)); + patch->setOrder(order); + patch->setVanilla(true); + patch->setRemovable(true); + patch->setMovable(true); + loadedPatches[uid] = patch; } - lwjglPatch->setOrder(-1); - profile->appendPatch(lwjglPatch); - } -} + }; + loadSpecial("net.minecraftforge", 5); + loadSpecial("com.mumfrey.liteloader", 10); -void OneSixProfileStrategy::loadUserPatches() -{ - // load all patches, put into map for ordering, apply in the right order + // now add all the patches by user sort order ProfileUtils::PatchOrder userOrder; ProfileUtils::readOverrideOrders(FS::PathCombine(m_instance->instanceRoot(), "order.json"), userOrder); - QDir patches(FS::PathCombine(m_instance->instanceRoot(),"patches")); - QSet<QString> seen_extra; - - // first, load things by sort order. - for (auto id : userOrder) + bool orderIsDirty = false; + for (auto uid : userOrder) { // ignore builtins - if (id == "net.minecraft") + if (uid == "net.minecraft") continue; - if (id == "org.lwjgl") + if (uid == "org.lwjgl") continue; - // parse the file - QString filename = patches.absoluteFilePath(id + ".json"); - QFileInfo finfo(filename); - if(!finfo.exists()) + // ordering has a patch that is gone? + if(!loadedPatches.contains(uid)) { - qDebug() << "Patch file " << filename << " was deleted by external means..."; + orderIsDirty = true; continue; } - qDebug() << "Reading" << filename << "by user order"; - VersionFilePtr file = ProfileUtils::parseJsonFile(finfo, false); - // sanity check. prevent tampering with files. - if (file->fileId != id) - { - file->addProblem(PROBLEM_WARNING, QObject::tr("load id %1 does not match internal id %2").arg(id, file->fileId)); - seen_extra.insert(file->fileId); - } - file->setRemovable(true); - file->setMovable(true); - // HACK: ignore assets from other version files than Minecraft - // workaround for stupid assets issue caused by amazon: - // https://www.theregister.co.uk/2017/02/28/aws_is_awol_as_s3_goes_haywire/ - file->assets = QString(); - file->mojangAssetIndex.reset(); - // HACK - profile->appendPatch(file); + profile->appendPatch(loadedPatches.take(uid)); } - // now load the rest by internal preference. - QMultiMap<int, VersionFilePtr> files; - for (auto info : patches.entryInfoList(QStringList() << "*.json", QDir::Files)) + + // is there anything left to sort? + if(loadedPatches.isEmpty()) { - // parse the file - qDebug() << "Reading" << info.fileName(); - auto file = ProfileUtils::parseJsonFile(info, true); - // ignore builtins - if (file->fileId == "net.minecraft") - continue; - if (file->fileId == "org.lwjgl") - continue; - // do not load versions with broken IDs twice - if(seen_extra.contains(file->fileId)) - continue; - // do not load what we already loaded in the first pass - if (userOrder.contains(file->fileId)) - continue; - file->setRemovable(true); - file->setMovable(true); - // HACK: ignore assets from other version files than Minecraft - // workaround for stupid assets issue caused by amazon: - // https://www.theregister.co.uk/2017/02/28/aws_is_awol_as_s3_goes_haywire/ - file->assets = QString(); - file->mojangAssetIndex.reset(); - // HACK - files.insert(file->order, file); + // TODO: save the order here? + return; + } + + // inserting into multimap by order number as key sorts the patches and detects duplicates + QMultiMap<int, ProfilePatchPtr> files; + auto iter = loadedPatches.begin(); + while(iter != loadedPatches.end()) + { + files.insert((*iter)->getOrder(), *iter); + iter++; } - QSet<int> seen; + + // then just extract the patches and put them in the list for (auto order : files.keys()) { - if(seen.contains(order)) - continue; - seen.insert(order); const auto &values = files.values(order); - if(values.size() == 1) - { - profile->appendPatch(values[0]); - continue; - } - for(auto &file: values) + for(auto &value: values) { - QStringList list; - for(auto &file2: values) - { - if(file != file2) - list.append(file2->name); - } - file->addProblem(PROBLEM_WARNING, QObject::tr("%1 has the same order as the following components:\n%2").arg(file->name, list.join(", "))); - profile->appendPatch(file); + // TODO: put back the insertion of problem messages here, so the user knows about the id duplication + profile->appendPatch(value); } } + // TODO: save the order here? } @@ -266,7 +243,10 @@ bool OneSixProfileStrategy::removePatch(ProfilePatchPtr patch) return false; } } - + if(!m_instance->getComponentVersion(patch->getID()).isEmpty()) + { + m_instance->setComponentVersion(patch->getID(), QString()); + } auto preRemoveJarMod = [&](JarmodPtr jarMod) -> bool { @@ -285,7 +265,8 @@ bool OneSixProfileStrategy::removePatch(ProfilePatchPtr patch) return true; }; - for(auto &jarmod: patch->getJarMods()) + auto &jarMods = patch->getVersionFile()->jarMods; + for(auto &jarmod: jarMods) { ok &= preRemoveJarMod(jarmod); } @@ -405,12 +386,9 @@ bool OneSixProfileStrategy::installJarMods(QStringList filepaths) jarMod->originalName = sourceInfo.completeBaseName(); f->jarMods.append(jarMod); f->name = target_name; - f->fileId = target_id; + f->uid = target_id; f->order = profile->getFreeOrderNumber(); QString patchFileName = FS::PathCombine(patchDir, target_id + ".json"); - f->filename = patchFileName; - f->setMovable(true); - f->setRemovable(true); QFile file(patchFileName); if (!file.open(QFile::WriteOnly)) @@ -421,7 +399,11 @@ bool OneSixProfileStrategy::installJarMods(QStringList filepaths) } file.write(OneSixVersionFormat::versionFileToJson(f, true).toJson()); file.close(); - profile->appendPatch(f); + + auto patch = std::make_shared<ProfilePatch>(f, patchFileName); + patch->setMovable(true); + patch->setRemovable(true); + profile->appendPatch(patch); } profile->saveCurrentOrder(); profile->reapplyPatches(); diff --git a/api/logic/minecraft/onesix/OneSixUpdate.cpp b/api/logic/minecraft/onesix/OneSixUpdate.cpp index 4bc80bfe..bf234189 100644 --- a/api/logic/minecraft/onesix/OneSixUpdate.cpp +++ b/api/logic/minecraft/onesix/OneSixUpdate.cpp @@ -24,7 +24,6 @@ #include <QDataStream> #include "BaseInstance.h" -#include "minecraft/MinecraftVersionList.h" #include "minecraft/MinecraftProfile.h" #include "minecraft/Library.h" #include "net/URLConstants.h" @@ -35,6 +34,9 @@ #include "update/FMLLibrariesTask.h" #include "update/AssetUpdateTask.h" +#include <meta/Index.h> +#include <meta/Version.h> + OneSixUpdate::OneSixUpdate(OneSixInstance *inst, QObject *parent) : Task(parent), m_inst(inst) { // create folders @@ -44,29 +46,23 @@ OneSixUpdate::OneSixUpdate(OneSixInstance *inst, QObject *parent) : Task(parent) // add a version update task, if necessary { - auto list = std::dynamic_pointer_cast<MinecraftVersionList>(ENV.getVersionList("net.minecraft")); - auto version = std::dynamic_pointer_cast<MinecraftVersion>(list->findVersion(m_inst->intendedVersionId())); - if (version == nullptr) - { - // don't do anything if it was invalid - m_preFailure = tr("The specified Minecraft version is invalid. Choose a different one."); - } - else if (m_inst->providesVersionFile() || !version->needsUpdate()) + /* + * FIXME: there are some corner cases here that remain unhandled: + * what if local load succeeds but remote fails? The version is still usable... + */ + // FIXME: derive this from the actual list of version patches... + auto loadVersion = [&](const QString & uid, const QString & version) { - qDebug() << "Instance either provides a version file or doesn't need an update."; - } - else - { - auto versionUpdateTask = list->createUpdateTask(m_inst->intendedVersionId()); - if (!versionUpdateTask) - { - qDebug() << "Didn't spawn an update task."; - } - else + auto obj = ENV.metadataIndex()->get(uid, version); + obj->load(); + auto task = obj->getCurrentTask(); + if(task) { - m_tasks.append(versionUpdateTask); + m_tasks.append(task.unwrap()); } - } + }; + loadVersion("org.lwjgl", m_inst->getComponentVersion("org.lwjgl")); + loadVersion("net.minecraft", m_inst->getComponentVersion("net.minecraft")); } // libraries download @@ -117,11 +113,20 @@ void OneSixUpdate::next() return; } auto task = m_tasks[m_currentTask]; + // if the task is already finished by the time we look at it, skip it + if(task->isFinished()) + { + next(); + } connect(task.get(), &Task::succeeded, this, &OneSixUpdate::subtaskSucceeded); connect(task.get(), &Task::failed, this, &OneSixUpdate::subtaskFailed); connect(task.get(), &Task::progress, this, &OneSixUpdate::progress); connect(task.get(), &Task::status, this, &OneSixUpdate::setStatus); - task->start(); + // if the task is already running, do not start it again + if(!task->isRunning()) + { + task->start(); + } } void OneSixUpdate::subtaskSucceeded() diff --git a/api/logic/minecraft/onesix/OneSixVersionFormat.cpp b/api/logic/minecraft/onesix/OneSixVersionFormat.cpp index 541fb109..266bd4bd 100644 --- a/api/logic/minecraft/onesix/OneSixVersionFormat.cpp +++ b/api/logic/minecraft/onesix/OneSixVersionFormat.cpp @@ -1,7 +1,6 @@ #include "OneSixVersionFormat.h" #include <Json.h> #include "minecraft/ParseUtils.h" -#include <minecraft/MinecraftVersion.h> #include <minecraft/VersionBuildError.h> #include <minecraft/MojangVersionFormat.h> @@ -62,10 +61,19 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc } out->name = root.value("name").toString(); - out->fileId = root.value("fileId").toString(); + + if(root.contains("uid")) + { + out->uid = root.value("uid").toString(); + } + else + { + out->uid = root.value("fileId").toString(); + } + out->version = root.value("version").toString(); out->dependsOnMinecraftVersion = root.value("mcVersion").toString(); - out->filename = filename; + // out->filename = filename; MojangVersionFormat::readVersionProperties(root, out.get()); @@ -120,7 +128,8 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc bool hasLibs = root.contains("libraries"); if (hasPlusLibs && hasLibs) { - out->addProblem(PROBLEM_WARNING, QObject::tr("Version file has both '+libraries' and 'libraries'. This is no longer supported.")); + out->addProblem(ProblemSeverity::Warning, + QObject::tr("Version file has both '+libraries' and 'libraries'. This is no longer supported.")); readLibs("libraries"); readLibs("+libraries"); } @@ -136,23 +145,23 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc /* removed features that shouldn't be used */ if (root.contains("tweakers")) { - out->addProblem(PROBLEM_ERROR, QObject::tr("Version file contains unsupported element 'tweakers'")); + out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element 'tweakers'")); } if (root.contains("-libraries")) { - out->addProblem(PROBLEM_ERROR, QObject::tr("Version file contains unsupported element '-libraries'")); + out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element '-libraries'")); } if (root.contains("-tweakers")) { - out->addProblem(PROBLEM_ERROR, QObject::tr("Version file contains unsupported element '-tweakers'")); + out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element '-tweakers'")); } if (root.contains("-minecraftArguments")) { - out->addProblem(PROBLEM_ERROR, QObject::tr("Version file contains unsupported element '-minecraftArguments'")); + out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element '-minecraftArguments'")); } if (root.contains("+minecraftArguments")) { - out->addProblem(PROBLEM_ERROR, QObject::tr("Version file contains unsupported element '+minecraftArguments'")); + out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element '+minecraftArguments'")); } return out; } @@ -165,7 +174,10 @@ QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch root.insert("order", patch->order); } writeString(root, "name", patch->name); - writeString(root, "fileId", patch->fileId); + + writeString(root, "uid", patch->uid); + writeString(root, "fileId", patch->uid); + writeString(root, "version", patch->version); writeString(root, "mcVersion", patch->dependsOnMinecraftVersion); diff --git a/api/logic/minecraft/onesix/update/LibrariesTask.cpp b/api/logic/minecraft/onesix/update/LibrariesTask.cpp index f60c2b5e..3e6bb12a 100644 --- a/api/logic/minecraft/onesix/update/LibrariesTask.cpp +++ b/api/logic/minecraft/onesix/update/LibrariesTask.cpp @@ -35,19 +35,23 @@ void LibrariesTask::executeTask() downloadJob.reset(job); } - auto libs = profile->getLibraries(); - auto metacache = ENV.metacache(); QList<LibraryPtr> brokenLocalLibs; QStringList failedFiles; - for (auto lib : libs) + auto createJobs = [&](const QList<LibraryPtr> & libs) { - auto dls = lib->getDownloads(currentSystem, metacache.get(), failedFiles, inst->getLocalLibraryPath()); - for(auto dl : dls) + for (auto lib : libs) { - downloadJob->addNetAction(dl); + auto dls = lib->getDownloads(currentSystem, metacache.get(), failedFiles, inst->getLocalLibraryPath()); + for(auto dl : dls) + { + downloadJob->addNetAction(dl); + } } - } + }; + createJobs(profile->getLibraries()); + createJobs(profile->getNativeLibraries()); + // FIXME: this is never filled!!!! if (!brokenLocalLibs.empty()) { |