diff options
Diffstat (limited to 'api/logic/minecraft/onesix/OneSixProfileStrategy.cpp')
-rw-r--r-- | api/logic/minecraft/onesix/OneSixProfileStrategy.cpp | 226 |
1 files changed, 104 insertions, 122 deletions
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(); |