From fede712a26937c5c0815cb9ed62320a8611794eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Wed, 11 Oct 2017 23:04:24 +0200 Subject: NOISSUE rename MinecraftProfile to ComponentList It is realistically a list of components. The fact that it also holds the final launch parameters is a design bug. --- api/logic/CMakeLists.txt | 4 +- api/logic/InstanceImportTask.cpp | 4 +- api/logic/meta/Version.cpp | 2 +- api/logic/minecraft/ComponentList.cpp | 1125 ++++++++++++++++++++++ api/logic/minecraft/ComponentList.h | 203 ++++ api/logic/minecraft/MinecraftInstance.cpp | 12 +- api/logic/minecraft/MinecraftInstance.h | 6 +- api/logic/minecraft/MinecraftProfile.cpp | 1125 ---------------------- api/logic/minecraft/MinecraftProfile.h | 203 ---- api/logic/minecraft/MinecraftUpdate.cpp | 4 +- api/logic/minecraft/OneSixVersionFormat.h | 2 +- api/logic/minecraft/ProfilePatch.cpp | 4 +- api/logic/minecraft/ProfilePatch.h | 4 +- api/logic/minecraft/VersionFile.cpp | 4 +- api/logic/minecraft/VersionFile.h | 4 +- api/logic/minecraft/launch/ModMinecraftJar.cpp | 4 +- api/logic/minecraft/legacy/LegacyUpgradeTask.cpp | 4 +- api/logic/minecraft/update/AssetUpdateTask.cpp | 6 +- api/logic/minecraft/update/FMLLibrariesTask.cpp | 4 +- api/logic/minecraft/update/LibrariesTask.cpp | 4 +- application/pages/ModFolderPage.cpp | 4 +- application/pages/VersionPage.cpp | 18 +- application/pages/VersionPage.h | 6 +- 23 files changed, 1378 insertions(+), 1378 deletions(-) create mode 100644 api/logic/minecraft/ComponentList.cpp create mode 100644 api/logic/minecraft/ComponentList.h delete mode 100644 api/logic/minecraft/MinecraftProfile.cpp delete mode 100644 api/logic/minecraft/MinecraftProfile.h diff --git a/api/logic/CMakeLists.txt b/api/logic/CMakeLists.txt index 38b15286..e5047d38 100644 --- a/api/logic/CMakeLists.txt +++ b/api/logic/CMakeLists.txt @@ -237,8 +237,8 @@ set(MINECRAFT_SOURCES minecraft/GradleSpecifier.h minecraft/MinecraftInstance.cpp minecraft/MinecraftInstance.h - minecraft/MinecraftProfile.cpp - minecraft/MinecraftProfile.h + minecraft/ComponentList.cpp + minecraft/ComponentList.h minecraft/MinecraftUpdate.h minecraft/MinecraftUpdate.cpp minecraft/MojangVersionFormat.cpp diff --git a/api/logic/InstanceImportTask.cpp b/api/logic/InstanceImportTask.cpp index 4e841694..e2782cd8 100644 --- a/api/logic/InstanceImportTask.cpp +++ b/api/logic/InstanceImportTask.cpp @@ -11,7 +11,7 @@ // FIXME: this does not belong here, it's Minecraft/Flame specific #include "minecraft/MinecraftInstance.h" -#include "minecraft/MinecraftProfile.h" +#include "minecraft/ComponentList.h" #include "minecraft/flame/FileResolvingTask.h" #include "minecraft/flame/PackManifest.h" #include "Json.h" @@ -293,7 +293,7 @@ void InstanceImportTask::processFlame() qDebug() << info.fileName(); jarMods.push_back(info.absoluteFilePath()); } - auto profile = instance.getMinecraftProfile(); + auto profile = instance.getComponentList(); profile->installJarMods(jarMods); // nuke the original files FS::deletePath(jarmodsPath); diff --git a/api/logic/meta/Version.cpp b/api/logic/meta/Version.cpp index b00a29e7..bf739157 100644 --- a/api/logic/meta/Version.cpp +++ b/api/logic/meta/Version.cpp @@ -18,7 +18,7 @@ #include #include "JsonFormat.h" -#include "minecraft/MinecraftProfile.h" +#include "minecraft/ComponentList.h" Meta::Version::Version(const QString &uid, const QString &version) : BaseVersion(), m_uid(uid), m_version(version) diff --git a/api/logic/minecraft/ComponentList.cpp b/api/logic/minecraft/ComponentList.cpp new file mode 100644 index 00000000..8ce1fded --- /dev/null +++ b/api/logic/minecraft/ComponentList.cpp @@ -0,0 +1,1125 @@ +/* Copyright 2013-2017 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 +#include +#include +#include +#include +#include + +#include "minecraft/ComponentList.h" +#include "Exception.h" +#include +#include +#include +#include +#include +#include +#include + +ComponentList::ComponentList(MinecraftInstance * instance) + : QAbstractListModel() +{ + m_instance = instance; + clear(); +} + +ComponentList::~ComponentList() +{ +} + +void ComponentList::reload() +{ + beginResetModel(); + load_internal(); + reapplyPatches(); + endResetModel(); +} + +void ComponentList::clear() +{ + m_minecraftVersion.clear(); + m_minecraftVersionType.clear(); + m_minecraftAssets.reset(); + m_minecraftArguments.clear(); + m_tweakers.clear(); + m_mainClass.clear(); + m_appletClass.clear(); + m_libraries.clear(); + m_traits.clear(); + m_jarMods.clear(); + m_mainJar.reset(); + m_problemSeverity = ProblemSeverity::None; +} + +void ComponentList::clearPatches() +{ + beginResetModel(); + m_patches.clear(); + endResetModel(); +} + +void ComponentList::appendPatch(ProfilePatchPtr patch) +{ + int index = m_patches.size(); + beginInsertRows(QModelIndex(), index, index); + m_patches.append(patch); + endInsertRows(); +} + +bool ComponentList::remove(const int index) +{ + auto patch = versionPatch(index); + if (!patch->isRemovable()) + { + qDebug() << "Patch" << patch->getID() << "is non-removable"; + return false; + } + + if(!removePatch_internal(patch)) + { + qCritical() << "Patch" << patch->getID() << "could not be removed"; + return false; + } + + beginRemoveRows(QModelIndex(), index, index); + m_patches.removeAt(index); + endRemoveRows(); + reapplyPatches(); + saveCurrentOrder(); + return true; +} + +bool ComponentList::remove(const QString id) +{ + int i = 0; + for (auto patch : m_patches) + { + if (patch->getID() == id) + { + return remove(i); + } + i++; + } + return false; +} + +bool ComponentList::customize(int index) +{ + auto patch = versionPatch(index); + if (!patch->isCustomizable()) + { + qDebug() << "Patch" << patch->getID() << "is not customizable"; + return false; + } + if(!customizePatch_internal(patch)) + { + qCritical() << "Patch" << patch->getID() << "could not be customized"; + return false; + } + reapplyPatches(); + saveCurrentOrder(); + // FIXME: maybe later in unstable + // emit dataChanged(createIndex(index, 0), createIndex(index, columnCount(QModelIndex()) - 1)); + return true; +} + +bool ComponentList::revertToBase(int index) +{ + auto patch = versionPatch(index); + if (!patch->isRevertible()) + { + qDebug() << "Patch" << patch->getID() << "is not revertible"; + return false; + } + if(!revertPatch_internal(patch)) + { + qCritical() << "Patch" << patch->getID() << "could not be reverted"; + return false; + } + reapplyPatches(); + saveCurrentOrder(); + // FIXME: maybe later in unstable + // emit dataChanged(createIndex(index, 0), createIndex(index, columnCount(QModelIndex()) - 1)); + return true; +} + +ProfilePatchPtr ComponentList::versionPatch(const QString &id) +{ + for (auto patch : m_patches) + { + if (patch->getID() == id) + { + return patch; + } + } + return nullptr; +} + +ProfilePatchPtr ComponentList::versionPatch(int index) +{ + if(index < 0 || index >= m_patches.size()) + return nullptr; + return m_patches[index]; +} + +bool ComponentList::isVanilla() +{ + for(auto patchptr: m_patches) + { + if(patchptr->isCustom()) + return false; + } + return true; +} + +bool ComponentList::revertToVanilla() +{ + // remove patches, if present + auto VersionPatchesCopy = m_patches; + for(auto & it: VersionPatchesCopy) + { + if (!it->isCustom()) + { + continue; + } + if(it->isRevertible() || it->isRemovable()) + { + if(!remove(it->getID())) + { + qWarning() << "Couldn't remove" << it->getID() << "from profile!"; + reapplyPatches(); + saveCurrentOrder(); + return false; + } + } + } + reapplyPatches(); + saveCurrentOrder(); + return true; +} + +QVariant ComponentList::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + int row = index.row(); + int column = index.column(); + + if (row < 0 || row >= m_patches.size()) + return QVariant(); + + auto patch = m_patches.at(row); + + if (role == Qt::DisplayRole) + { + switch (column) + { + case 0: + return m_patches.at(row)->getName(); + case 1: + { + if(patch->isCustom()) + { + return QString("%1 (Custom)").arg(patch->getVersion()); + } + else + { + return patch->getVersion(); + } + } + default: + return QVariant(); + } + } + if(role == Qt::DecorationRole) + { + switch(column) + { + case 0: + { + auto severity = patch->getProblemSeverity(); + switch (severity) + { + case ProblemSeverity::Warning: + return "warning"; + case ProblemSeverity::Error: + return "error"; + default: + return QVariant(); + } + } + default: + { + return QVariant(); + } + } + } + return QVariant(); +} +QVariant ComponentList::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal) + { + if (role == Qt::DisplayRole) + { + switch (section) + { + case 0: + return tr("Name"); + case 1: + return tr("Version"); + default: + return QVariant(); + } + } + } + return QVariant(); +} +Qt::ItemFlags ComponentList::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return Qt::NoItemFlags; + return Qt::ItemIsSelectable | Qt::ItemIsEnabled; +} + +int ComponentList::rowCount(const QModelIndex &parent) const +{ + return m_patches.size(); +} + +int ComponentList::columnCount(const QModelIndex &parent) const +{ + return 2; +} + +void ComponentList::saveCurrentOrder() const +{ + ProfileUtils::PatchOrder order; + for(auto item: m_patches) + { + if(!item->isMoveable()) + continue; + order.append(item->getID()); + } + saveOrder_internal(order); +} + +void ComponentList::move(const int index, const MoveDirection direction) +{ + int theirIndex; + if (direction == MoveUp) + { + theirIndex = index - 1; + } + else + { + theirIndex = index + 1; + } + + if (index < 0 || index >= m_patches.size()) + return; + if (theirIndex >= rowCount()) + theirIndex = rowCount() - 1; + if (theirIndex == -1) + theirIndex = rowCount() - 1; + if (index == theirIndex) + return; + int togap = theirIndex > index ? theirIndex + 1 : theirIndex; + + auto from = versionPatch(index); + auto to = versionPatch(theirIndex); + + if (!from || !to || !to->isMoveable() || !from->isMoveable()) + { + return; + } + beginMoveRows(QModelIndex(), index, index, QModelIndex(), togap); + m_patches.swap(index, theirIndex); + endMoveRows(); + reapplyPatches(); + saveCurrentOrder(); +} +void ComponentList::resetOrder() +{ + resetOrder_internal(); + reload(); +} + +bool ComponentList::reapplyPatches() +{ + try + { + clear(); + for(auto file: m_patches) + { + qDebug() << "Applying" << file->getID() << (file->getProblemSeverity() == ProblemSeverity::Error ? "ERROR" : "GOOD"); + file->applyTo(this); + } + } + catch (Exception & error) + { + clear(); + qWarning() << "Couldn't apply profile patches because: " << error.cause(); + return false; + } + return true; +} + +static void applyString(const QString & from, QString & to) +{ + if(from.isEmpty()) + return; + to = from; +} + +void ComponentList::applyMinecraftVersion(const QString& id) +{ + applyString(id, this->m_minecraftVersion); +} + +void ComponentList::applyAppletClass(const QString& appletClass) +{ + applyString(appletClass, this->m_appletClass); +} + +void ComponentList::applyMainClass(const QString& mainClass) +{ + applyString(mainClass, this->m_mainClass); +} + +void ComponentList::applyMinecraftArguments(const QString& minecraftArguments) +{ + applyString(minecraftArguments, this->m_minecraftArguments); +} + +void ComponentList::applyMinecraftVersionType(const QString& type) +{ + applyString(type, this->m_minecraftVersionType); +} + +void ComponentList::applyMinecraftAssets(MojangAssetIndexInfo::Ptr assets) +{ + if(assets) + { + m_minecraftAssets = assets; + } +} + +void ComponentList::applyTraits(const QSet& traits) +{ + this->m_traits.unite(traits); +} + +void ComponentList::applyTweakers(const QStringList& tweakers) +{ + // if the applied tweakers override an existing one, skip it. this effectively moves it later in the sequence + QStringList newTweakers; + for(auto & tweaker: m_tweakers) + { + if (tweakers.contains(tweaker)) + { + continue; + } + newTweakers.append(tweaker); + } + // then just append the new tweakers (or moved original ones) + newTweakers += tweakers; + m_tweakers = newTweakers; +} + +void ComponentList::applyJarMods(const QList& jarMods) +{ + this->m_jarMods.append(jarMods); +} + +static int findLibraryByName(QList *haystack, const GradleSpecifier &needle) +{ + int retval = -1; + for (int i = 0; i < haystack->size(); ++i) + { + if (haystack->at(i)->rawName().matchName(needle)) + { + // only one is allowed. + if (retval != -1) + return -1; + retval = i; + } + } + return retval; +} + +void ComponentList::applyMods(const QList& mods) +{ + QList * list = &m_mods; + for(auto & mod: mods) + { + auto modCopy = Library::limitedCopy(mod); + + // find the mod by name. + const int index = findLibraryByName(list, mod->rawName()); + // mod not found? just add it. + if (index < 0) + { + list->append(modCopy); + return; + } + + auto existingLibrary = list->at(index); + // if we are higher it means we should update + if (Version(mod->version()) > Version(existingLibrary->version())) + { + list->replace(index, modCopy); + } + } +} + +void ComponentList::applyLibrary(LibraryPtr library) +{ + if(!library->isActive()) + { + return; + } + + QList * list = &m_libraries; + if(library->isNative()) + { + list = &m_nativeLibraries; + } + + auto libraryCopy = Library::limitedCopy(library); + + // find the library by name. + const int index = findLibraryByName(list, library->rawName()); + // library not found? just add it. + if (index < 0) + { + list->append(libraryCopy); + return; + } + + auto existingLibrary = list->at(index); + // if we are higher it means we should update + if (Version(library->version()) > Version(existingLibrary->version())) + { + list->replace(index, libraryCopy); + } +} + +const LibraryPtr ComponentList::getMainJar() const +{ + return m_mainJar; +} + +void ComponentList::applyMainJar(LibraryPtr jar) +{ + if(jar) + { + m_mainJar = jar; + } +} + +void ComponentList::applyProblemSeverity(ProblemSeverity severity) +{ + if (m_problemSeverity < severity) + { + m_problemSeverity = severity; + } +} + + +QString ComponentList::getMinecraftVersion() const +{ + return m_minecraftVersion; +} + +QString ComponentList::getAppletClass() const +{ + return m_appletClass; +} + +QString ComponentList::getMainClass() const +{ + return m_mainClass; +} + +const QSet &ComponentList::getTraits() const +{ + return m_traits; +} + +const QStringList & ComponentList::getTweakers() const +{ + return m_tweakers; +} + +bool ComponentList::hasTrait(const QString& trait) const +{ + return m_traits.contains(trait); +} + +ProblemSeverity ComponentList::getProblemSeverity() const +{ + return m_problemSeverity; +} + +QString ComponentList::getMinecraftVersionType() const +{ + return m_minecraftVersionType; +} + +std::shared_ptr ComponentList::getMinecraftAssets() const +{ + if(!m_minecraftAssets) + { + return std::make_shared("legacy"); + } + return m_minecraftAssets; +} + +QString ComponentList::getMinecraftArguments() const +{ + return m_minecraftArguments; +} + +const QList & ComponentList::getJarMods() const +{ + return m_jarMods; +} + +const QList & ComponentList::getLibraries() const +{ + return m_libraries; +} + +const QList & ComponentList::getNativeLibraries() const +{ + return m_nativeLibraries; +} + +void ComponentList::getLibraryFiles(const QString& architecture, QStringList& jars, QStringList& nativeJars, const QString& overridePath, const QString& tempPath) const +{ + QStringList native32, native64; + jars.clear(); + nativeJars.clear(); + for (auto lib : getLibraries()) + { + lib->getApplicableFiles(currentSystem, jars, nativeJars, native32, native64, overridePath); + } + // NOTE: order is important here, add main jar last to the lists + if(m_mainJar) + { + // FIXME: HACK!! jar modding is weird and unsystematic! + if(m_jarMods.size()) + { + QDir tempDir(tempPath); + jars.append(tempDir.absoluteFilePath("minecraft.jar")); + } + else + { + m_mainJar->getApplicableFiles(currentSystem, jars, nativeJars, native32, native64, overridePath); + } + } + for (auto lib : getNativeLibraries()) + { + lib->getApplicableFiles(currentSystem, jars, nativeJars, native32, native64, overridePath); + } + if(architecture == "32") + { + nativeJars.append(native32); + } + else if(architecture == "64") + { + nativeJars.append(native64); + } +} + +void ComponentList::installJarMods(QStringList selectedFiles) +{ + installJarMods_internal(selectedFiles); +} + +void ComponentList::installCustomJar(QString selectedFile) +{ + installCustomJar_internal(selectedFile); +} + + +/* + * TODO: get rid of this. Get rid of all order numbers. + */ +int ComponentList::getFreeOrderNumber() +{ + int largest = 100; + // yes, I do realize this is dumb. The order thing itself is dumb. and to be removed next. + for(auto thing: m_patches) + { + int order = thing->getOrder(); + if(order > largest) + largest = order; + } + return largest + 1; +} + +void ComponentList::upgradeDeprecatedFiles_internal() +{ + auto versionJsonPath = FS::PathCombine(m_instance->instanceRoot(), "version.json"); + auto customJsonPath = FS::PathCombine(m_instance->instanceRoot(), "custom.json"); + auto mcJson = FS::PathCombine(m_instance->instanceRoot(), "patches" , "net.minecraft.json"); + + QString sourceFile; + QString renameFile; + + // convert old crap. + if(QFile::exists(customJsonPath)) + { + sourceFile = customJsonPath; + renameFile = versionJsonPath; + } + else if(QFile::exists(versionJsonPath)) + { + sourceFile = versionJsonPath; + } + if(!sourceFile.isEmpty() && !QFile::exists(mcJson)) + { + if(!FS::ensureFilePathExists(mcJson)) + { + qWarning() << "Couldn't create patches folder for" << m_instance->name(); + return; + } + if(!renameFile.isEmpty() && QFile::exists(renameFile)) + { + if(!QFile::rename(renameFile, renameFile + ".old")) + { + qWarning() << "Couldn't rename" << renameFile << "to" << renameFile + ".old" << "in" << m_instance->name(); + return; + } + } + auto file = ProfileUtils::parseJsonFile(QFileInfo(sourceFile), false); + ProfileUtils::removeLwjglFromPatch(file); + file->uid = "net.minecraft"; + file->version = file->minecraftVersion; + file->name = "Minecraft"; + auto data = OneSixVersionFormat::versionFileToJson(file, false).toJson(); + QSaveFile newPatchFile(mcJson); + if(!newPatchFile.open(QIODevice::WriteOnly)) + { + newPatchFile.cancelWriting(); + qWarning() << "Couldn't open main patch for writing in" << m_instance->name(); + return; + } + newPatchFile.write(data); + if(!newPatchFile.commit()) + { + qWarning() << "Couldn't save main patch in" << m_instance->name(); + return; + } + if(!QFile::rename(sourceFile, sourceFile + ".old")) + { + qWarning() << "Couldn't rename" << sourceFile << "to" << sourceFile + ".old" << "in" << m_instance->name(); + return; + } + } +} + +void ComponentList::loadDefaultBuiltinPatches_internal() +{ + auto addBuiltinPatch = [&](const QString &uid, const QString intendedVersion, int order) + { + auto jsonFilePath = FS::PathCombine(m_instance->instanceRoot(), "patches" , uid + ".json"); + // load up the base minecraft patch + ProfilePatchPtr profilePatch; + if(QFile::exists(jsonFilePath)) + { + auto file = ProfileUtils::parseJsonFile(QFileInfo(jsonFilePath), false); + if(file->version.isEmpty()) + { + file->version = intendedVersion; + } + profilePatch = std::make_shared(file, jsonFilePath); + profilePatch->setVanilla(false); + profilePatch->setRevertible(true); + } + else + { + auto metaVersion = ENV.metadataIndex()->get(uid, intendedVersion); + profilePatch = std::make_shared(metaVersion); + profilePatch->setVanilla(true); + } + profilePatch->setOrder(order); + appendPatch(profilePatch); + }; + addBuiltinPatch("net.minecraft", m_instance->getComponentVersion("net.minecraft"), -2); + addBuiltinPatch("org.lwjgl", m_instance->getComponentVersion("org.lwjgl"), -1); +} + +void ComponentList::loadUserPatches_internal() +{ + // first, collect all patches (that are not builtins of OneSix) and load them + QMap loadedPatches; + QDir patchesDir(FS::PathCombine(m_instance->instanceRoot(),"patches")); + for (auto info : patchesDir.entryInfoList(QStringList() << "*.json", QDir::Files)) + { + // 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(file, info.filePath()); + patch->setRemovable(true); + patch->setMovable(true); + if(ENV.metadataIndex()->hasUid(file->uid)) + { + // FIXME: requesting a uid/list creates it in the index... this allows reverting to possibly invalid versions... + patch->setRevertible(true); + } + 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)) + { + auto patch = std::make_shared(ENV.metadataIndex()->get(uid, patchVersion)); + patch->setOrder(order); + patch->setVanilla(true); + patch->setRemovable(true); + patch->setMovable(true); + loadedPatches[uid] = patch; + } + }; + loadSpecial("net.minecraftforge", 5); + loadSpecial("com.mumfrey.liteloader", 10); + + // now add all the patches by user sort order + ProfileUtils::PatchOrder userOrder; + ProfileUtils::readOverrideOrders(FS::PathCombine(m_instance->instanceRoot(), "order.json"), userOrder); + for (auto uid : userOrder) + { + // ignore builtins + if (uid == "net.minecraft") + continue; + if (uid == "org.lwjgl") + continue; + // ordering has a patch that is gone? + if(!loadedPatches.contains(uid)) + { + continue; + } + appendPatch(loadedPatches.take(uid)); + } + + // is there anything left to sort? + if(loadedPatches.isEmpty()) + { + // TODO: save the order here? + return; + } + + // inserting into multimap by order number as key sorts the patches and detects duplicates + QMultiMap files; + auto iter = loadedPatches.begin(); + while(iter != loadedPatches.end()) + { + files.insert((*iter)->getOrder(), *iter); + iter++; + } + + // then just extract the patches and put them in the list + for (auto order : files.keys()) + { + const auto &values = files.values(order); + for(auto &value: values) + { + // TODO: put back the insertion of problem messages here, so the user knows about the id duplication + appendPatch(value); + } + } + // TODO: save the order here? +} + + +void ComponentList::load_internal() +{ + clearPatches(); + upgradeDeprecatedFiles_internal(); + loadDefaultBuiltinPatches_internal(); + loadUserPatches_internal(); +} + +bool ComponentList::saveOrder_internal(ProfileUtils::PatchOrder order) const +{ + return ProfileUtils::writeOverrideOrders(FS::PathCombine(m_instance->instanceRoot(), "order.json"), order); +} + +bool ComponentList::resetOrder_internal() +{ + return QDir(m_instance->instanceRoot()).remove("order.json"); +} + +bool ComponentList::removePatch_internal(ProfilePatchPtr patch) +{ + bool ok = true; + // first, remove the patch file. this ensures it's not used anymore + auto fileName = patch->getFilename(); + if(fileName.size()) + { + QFile patchFile(fileName); + if(patchFile.exists() && !patchFile.remove()) + { + qCritical() << "File" << fileName << "could not be removed because:" << patchFile.errorString(); + return false; + } + } + if(!m_instance->getComponentVersion(patch->getID()).isEmpty()) + { + m_instance->setComponentVersion(patch->getID(), QString()); + } + + // FIXME: we need a generic way of removing local resources, not just jar mods... + auto preRemoveJarMod = [&](LibraryPtr jarMod) -> bool + { + if (!jarMod->isLocal()) + { + return true; + } + QStringList jar, temp1, temp2, temp3; + jarMod->getApplicableFiles(currentSystem, jar, temp1, temp2, temp3, m_instance->jarmodsPath().absolutePath()); + QFileInfo finfo (jar[0]); + if(finfo.exists()) + { + QFile jarModFile(jar[0]); + if(!jarModFile.remove()) + { + qCritical() << "File" << jar[0] << "could not be removed because:" << jarModFile.errorString(); + return false; + } + return true; + } + return true; + }; + + auto &jarMods = patch->getVersionFile()->jarMods; + for(auto &jarmod: jarMods) + { + ok &= preRemoveJarMod(jarmod); + } + return ok; +} + +bool ComponentList::customizePatch_internal(ProfilePatchPtr patch) +{ + if(patch->isCustom()) + { + return false; + } + + auto filename = FS::PathCombine(m_instance->instanceRoot(), "patches" , patch->getID() + ".json"); + if(!FS::ensureFilePathExists(filename)) + { + return false; + } + // FIXME: get rid of this try-catch. + try + { + QSaveFile jsonFile(filename); + if(!jsonFile.open(QIODevice::WriteOnly)) + { + return false; + } + auto vfile = patch->getVersionFile(); + if(!vfile) + { + return false; + } + auto document = OneSixVersionFormat::versionFileToJson(vfile, true); + jsonFile.write(document.toJson()); + if(!jsonFile.commit()) + { + return false; + } + load_internal(); + } + catch (Exception &error) + { + qWarning() << "Version could not be loaded:" << error.cause(); + } + return true; +} + +bool ComponentList::revertPatch_internal(ProfilePatchPtr patch) +{ + if(!patch->isCustom()) + { + // already not custom + return true; + } + auto filename = patch->getFilename(); + if(!QFile::exists(filename)) + { + // already gone / not custom + return true; + } + // just kill the file and reload + bool result = QFile::remove(filename); + // FIXME: get rid of this try-catch. + try + { + load_internal(); + } + catch (Exception &error) + { + qWarning() << "Version could not be loaded:" << error.cause(); + } + return result; +} + +bool ComponentList::installJarMods_internal(QStringList filepaths) +{ + QString patchDir = FS::PathCombine(m_instance->instanceRoot(), "patches"); + if(!FS::ensureFolderPathExists(patchDir)) + { + return false; + } + + if (!FS::ensureFolderPathExists(m_instance->jarModsDir())) + { + return false; + } + + for(auto filepath:filepaths) + { + QFileInfo sourceInfo(filepath); + auto uuid = QUuid::createUuid(); + QString id = uuid.toString().remove('{').remove('}'); + QString target_filename = id + ".jar"; + QString target_id = "org.multimc.jarmod." + id; + QString target_name = sourceInfo.completeBaseName() + " (jar mod)"; + QString finalPath = FS::PathCombine(m_instance->jarModsDir(), target_filename); + + QFileInfo targetInfo(finalPath); + if(targetInfo.exists()) + { + return false; + } + + if (!QFile::copy(sourceInfo.absoluteFilePath(),QFileInfo(finalPath).absoluteFilePath())) + { + return false; + } + + auto f = std::make_shared(); + auto jarMod = std::make_shared(); + jarMod->setRawName(GradleSpecifier("org.multimc.jarmods:" + id + ":1")); + jarMod->setFilename(target_filename); + jarMod->setDisplayName(sourceInfo.completeBaseName()); + jarMod->setHint("local"); + f->jarMods.append(jarMod); + f->name = target_name; + f->uid = target_id; + f->order = getFreeOrderNumber(); + QString patchFileName = FS::PathCombine(patchDir, target_id + ".json"); + + QFile file(patchFileName); + if (!file.open(QFile::WriteOnly)) + { + qCritical() << "Error opening" << file.fileName() + << "for reading:" << file.errorString(); + return false; + } + file.write(OneSixVersionFormat::versionFileToJson(f, true).toJson()); + file.close(); + + auto patch = std::make_shared(f, patchFileName); + patch->setMovable(true); + patch->setRemovable(true); + appendPatch(patch); + } + saveCurrentOrder(); + reapplyPatches(); + return true; +} + +bool ComponentList::installCustomJar_internal(QString filepath) +{ + QString patchDir = FS::PathCombine(m_instance->instanceRoot(), "patches"); + if(!FS::ensureFolderPathExists(patchDir)) + { + return false; + } + + QString libDir = m_instance->getLocalLibraryPath(); + if (!FS::ensureFolderPathExists(libDir)) + { + return false; + } + + auto specifier = GradleSpecifier("org.multimc:customjar:1"); + QFileInfo sourceInfo(filepath); + QString target_filename = specifier.getFileName(); + QString target_id = specifier.artifactId(); + QString target_name = sourceInfo.completeBaseName() + " (custom jar)"; + QString finalPath = FS::PathCombine(libDir, target_filename); + + QFileInfo jarInfo(finalPath); + if (jarInfo.exists()) + { + if(!QFile::remove(finalPath)) + { + return false; + } + } + if (!QFile::copy(filepath, finalPath)) + { + return false; + } + + auto f = std::make_shared(); + auto jarMod = std::make_shared(); + jarMod->setRawName(specifier); + jarMod->setDisplayName(sourceInfo.completeBaseName()); + jarMod->setHint("local"); + f->mainJar = jarMod; + f->name = target_name; + f->uid = target_id; + f->order = getFreeOrderNumber(); + QString patchFileName = FS::PathCombine(patchDir, target_id + ".json"); + + QFile file(patchFileName); + if (!file.open(QFile::WriteOnly)) + { + qCritical() << "Error opening" << file.fileName() + << "for reading:" << file.errorString(); + return false; + } + file.write(OneSixVersionFormat::versionFileToJson(f, true).toJson()); + file.close(); + + auto patch = std::make_shared(f, patchFileName); + patch->setMovable(true); + patch->setRemovable(true); + appendPatch(patch); + + saveCurrentOrder(); + reapplyPatches(); + return true; +} \ No newline at end of file diff --git a/api/logic/minecraft/ComponentList.h b/api/logic/minecraft/ComponentList.h new file mode 100644 index 00000000..a566d8f5 --- /dev/null +++ b/api/logic/minecraft/ComponentList.h @@ -0,0 +1,203 @@ +/* Copyright 2013-2017 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 + +#include +#include +#include + +#include "Library.h" +#include "ProfilePatch.h" +#include "ProfileUtils.h" +#include "BaseVersion.h" +#include "MojangDownloadInfo.h" + +#include "multimc_logic_export.h" + +class MinecraftInstance; + + +class MULTIMC_LOGIC_EXPORT ComponentList : public QAbstractListModel +{ + Q_OBJECT + +public: + explicit ComponentList(MinecraftInstance * instance); + virtual ~ComponentList(); + + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; + virtual int columnCount(const QModelIndex &parent) const override; + virtual Qt::ItemFlags flags(const QModelIndex &index) const override; + + /// is this version unchanged by the user? + bool isVanilla(); + + /// remove any customizations on top of whatever 'vanilla' means + bool revertToVanilla(); + + /// install more jar mods + void installJarMods(QStringList selectedFiles); + + /// install a jar/zip as a replacement for the main jar + void installCustomJar(QString selectedFile); + + /// DEPRECATED, remove ASAP + int getFreeOrderNumber(); + + enum MoveDirection { MoveUp, MoveDown }; + /// move patch file # up or down the list + void move(const int index, const MoveDirection direction); + + /// remove patch file # - including files/records + bool remove(const int index); + + /// remove patch file by id - including files/records + bool remove(const QString id); + + bool customize(int index); + + bool revertToBase(int index); + + void resetOrder(); + + /// reload all profile patches from storage, clear the profile and apply the patches + void reload(); + + /// clear the profile + void clear(); + + /// apply the patches. Catches all the errors and returns true/false for success/failure + bool reapplyPatches(); + +public: /* application of profile variables from patches */ + void applyMinecraftVersion(const QString& id); + void applyMainClass(const QString& mainClass); + void applyAppletClass(const QString& appletClass); + void applyMinecraftArguments(const QString& minecraftArguments); + void applyMinecraftVersionType(const QString& type); + void applyMinecraftAssets(MojangAssetIndexInfo::Ptr assets); + void applyTraits(const QSet &traits); + void applyTweakers(const QStringList &tweakers); + void applyJarMods(const QList &jarMods); + void applyMods(const QList &jarMods); + void applyLibrary(LibraryPtr library); + void applyMainJar(LibraryPtr jar); + void applyProblemSeverity(ProblemSeverity severity); + +public: /* getters for profile variables */ + QString getMinecraftVersion() const; + QString getMainClass() const; + QString getAppletClass() const; + QString getMinecraftVersionType() const; + MojangAssetIndexInfo::Ptr getMinecraftAssets() const; + QString getMinecraftArguments() const; + const QSet & getTraits() const; + const QStringList & getTweakers() const; + const QList & getJarMods() const; + const QList & getLibraries() const; + const QList & getNativeLibraries() const; + const LibraryPtr getMainJar() const; + void getLibraryFiles(const QString & architecture, QStringList & jars, QStringList & nativeJars, const QString & overridePath, + const QString & tempPath) const; + bool hasTrait(const QString & trait) const; + ProblemSeverity getProblemSeverity() const; + +public: + /// get the profile patch by id + ProfilePatchPtr versionPatch(const QString &id); + + /// get the profile patch by index + ProfilePatchPtr versionPatch(int index); + + /// save the current patch order + void saveCurrentOrder() const; + + /// Remove all the patches + void clearPatches(); + + /// Add the patch object to the internal list of patches + void appendPatch(ProfilePatchPtr patch); + +private: + void load_internal(); + bool resetOrder_internal(); + bool saveOrder_internal(ProfileUtils::PatchOrder order) const; + bool installJarMods_internal(QStringList filepaths); + bool installCustomJar_internal(QString filepath); + bool removePatch_internal(ProfilePatchPtr patch); + bool customizePatch_internal(ProfilePatchPtr patch); + bool revertPatch_internal(ProfilePatchPtr patch); + void loadDefaultBuiltinPatches_internal(); + void loadUserPatches_internal(); + void upgradeDeprecatedFiles_internal(); + +private: /* data */ + /// the version of Minecraft - jar to use + QString m_minecraftVersion; + + /// Release type - "release" or "snapshot" + QString m_minecraftVersionType; + + /// Assets type - "legacy" or a version ID + MojangAssetIndexInfo::Ptr m_minecraftAssets; + + /** + * 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 m_minecraftArguments; + + /// A list of all tweaker classes + QStringList m_tweakers; + + /// The main class to load first + QString m_mainClass; + + /// The applet class, for some very old minecraft releases + QString m_appletClass; + + /// the list of libraries + QList m_libraries; + + /// the main jar + LibraryPtr m_mainJar; + + /// the list of libraries + QList m_nativeLibraries; + + /// traits, collected from all the version files (version files can only add) + QSet m_traits; + + /// A list of jar mods. version files can add those. + QList m_jarMods; + + /// the list of mods + QList m_mods; + + ProblemSeverity m_problemSeverity = ProblemSeverity::None; + + /// list of attached profile patches + QList m_patches; + + // the instance this belongs to + MinecraftInstance *m_instance; +}; diff --git a/api/logic/minecraft/MinecraftInstance.cpp b/api/logic/minecraft/MinecraftInstance.cpp index 468b8ea1..e01d2616 100644 --- a/api/logic/minecraft/MinecraftInstance.cpp +++ b/api/logic/minecraft/MinecraftInstance.cpp @@ -31,7 +31,7 @@ #include "icons/IIconList.h" #include -#include "MinecraftProfile.h" +#include "ComponentList.h" #include "AssetsUtils.h" #include "MinecraftUpdate.h" @@ -133,7 +133,7 @@ bool MinecraftInstance::reload() void MinecraftInstance::createProfile() { - m_profile.reset(new MinecraftProfile(this)); + m_profile.reset(new ComponentList(this)); } void MinecraftInstance::reloadProfile() @@ -149,14 +149,14 @@ void MinecraftInstance::clearProfile() emit versionReloaded(); } -std::shared_ptr MinecraftInstance::getMinecraftProfile() const +std::shared_ptr MinecraftInstance::getComponentList() const { return m_profile; } QSet MinecraftInstance::traits() const { - auto version = getMinecraftProfile(); + auto version = getComponentList(); if (!version) { return {"version-incomplete"}; @@ -274,7 +274,7 @@ QStringList MinecraftInstance::getNativeJars() const QStringList MinecraftInstance::extraArguments() const { auto list = BaseInstance::extraArguments(); - auto version = getMinecraftProfile(); + auto version = getComponentList(); if (!version) return list; auto jarMods = getJarMods(); @@ -909,7 +909,7 @@ bool MinecraftInstance::setComponentVersion(const QString& uid, const QString& v { settings()->set("LiteloaderVersion", version); } - if(getMinecraftProfile()) + if(getComponentList()) { clearProfile(); } diff --git a/api/logic/minecraft/MinecraftInstance.h b/api/logic/minecraft/MinecraftInstance.h index d3a61c5d..417098da 100644 --- a/api/logic/minecraft/MinecraftInstance.h +++ b/api/logic/minecraft/MinecraftInstance.h @@ -9,7 +9,7 @@ class ModList; class WorldList; class LaunchStep; -class MinecraftProfile; +class ComponentList; class MULTIMC_LOGIC_EXPORT MinecraftInstance: public BaseInstance { @@ -52,7 +52,7 @@ public: ////// Profile management ////// void createProfile(); - std::shared_ptr getMinecraftProfile() const; + std::shared_ptr getComponentList() const; void reloadProfile(); void clearProfile(); bool reload() override; @@ -114,7 +114,7 @@ private: QString prettifyTimeDuration(int64_t duration); protected: // data - std::shared_ptr m_profile; + std::shared_ptr m_profile; mutable std::shared_ptr m_loader_mod_list; mutable std::shared_ptr m_core_mod_list; mutable std::shared_ptr m_resource_pack_list; diff --git a/api/logic/minecraft/MinecraftProfile.cpp b/api/logic/minecraft/MinecraftProfile.cpp deleted file mode 100644 index a9552af2..00000000 --- a/api/logic/minecraft/MinecraftProfile.cpp +++ /dev/null @@ -1,1125 +0,0 @@ -/* Copyright 2013-2017 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 -#include -#include -#include -#include -#include - -#include "minecraft/MinecraftProfile.h" -#include "Exception.h" -#include -#include -#include -#include -#include -#include -#include - -MinecraftProfile::MinecraftProfile(MinecraftInstance * instance) - : QAbstractListModel() -{ - m_instance = instance; - clear(); -} - -MinecraftProfile::~MinecraftProfile() -{ -} - -void MinecraftProfile::reload() -{ - beginResetModel(); - load_internal(); - reapplyPatches(); - endResetModel(); -} - -void MinecraftProfile::clear() -{ - m_minecraftVersion.clear(); - m_minecraftVersionType.clear(); - m_minecraftAssets.reset(); - m_minecraftArguments.clear(); - m_tweakers.clear(); - m_mainClass.clear(); - m_appletClass.clear(); - m_libraries.clear(); - m_traits.clear(); - m_jarMods.clear(); - m_mainJar.reset(); - m_problemSeverity = ProblemSeverity::None; -} - -void MinecraftProfile::clearPatches() -{ - beginResetModel(); - m_patches.clear(); - endResetModel(); -} - -void MinecraftProfile::appendPatch(ProfilePatchPtr patch) -{ - int index = m_patches.size(); - beginInsertRows(QModelIndex(), index, index); - m_patches.append(patch); - endInsertRows(); -} - -bool MinecraftProfile::remove(const int index) -{ - auto patch = versionPatch(index); - if (!patch->isRemovable()) - { - qDebug() << "Patch" << patch->getID() << "is non-removable"; - return false; - } - - if(!removePatch_internal(patch)) - { - qCritical() << "Patch" << patch->getID() << "could not be removed"; - return false; - } - - beginRemoveRows(QModelIndex(), index, index); - m_patches.removeAt(index); - endRemoveRows(); - reapplyPatches(); - saveCurrentOrder(); - return true; -} - -bool MinecraftProfile::remove(const QString id) -{ - int i = 0; - for (auto patch : m_patches) - { - if (patch->getID() == id) - { - return remove(i); - } - i++; - } - return false; -} - -bool MinecraftProfile::customize(int index) -{ - auto patch = versionPatch(index); - if (!patch->isCustomizable()) - { - qDebug() << "Patch" << patch->getID() << "is not customizable"; - return false; - } - if(!customizePatch_internal(patch)) - { - qCritical() << "Patch" << patch->getID() << "could not be customized"; - return false; - } - reapplyPatches(); - saveCurrentOrder(); - // FIXME: maybe later in unstable - // emit dataChanged(createIndex(index, 0), createIndex(index, columnCount(QModelIndex()) - 1)); - return true; -} - -bool MinecraftProfile::revertToBase(int index) -{ - auto patch = versionPatch(index); - if (!patch->isRevertible()) - { - qDebug() << "Patch" << patch->getID() << "is not revertible"; - return false; - } - if(!revertPatch_internal(patch)) - { - qCritical() << "Patch" << patch->getID() << "could not be reverted"; - return false; - } - reapplyPatches(); - saveCurrentOrder(); - // FIXME: maybe later in unstable - // emit dataChanged(createIndex(index, 0), createIndex(index, columnCount(QModelIndex()) - 1)); - return true; -} - -ProfilePatchPtr MinecraftProfile::versionPatch(const QString &id) -{ - for (auto patch : m_patches) - { - if (patch->getID() == id) - { - return patch; - } - } - return nullptr; -} - -ProfilePatchPtr MinecraftProfile::versionPatch(int index) -{ - if(index < 0 || index >= m_patches.size()) - return nullptr; - return m_patches[index]; -} - -bool MinecraftProfile::isVanilla() -{ - for(auto patchptr: m_patches) - { - if(patchptr->isCustom()) - return false; - } - return true; -} - -bool MinecraftProfile::revertToVanilla() -{ - // remove patches, if present - auto VersionPatchesCopy = m_patches; - for(auto & it: VersionPatchesCopy) - { - if (!it->isCustom()) - { - continue; - } - if(it->isRevertible() || it->isRemovable()) - { - if(!remove(it->getID())) - { - qWarning() << "Couldn't remove" << it->getID() << "from profile!"; - reapplyPatches(); - saveCurrentOrder(); - return false; - } - } - } - reapplyPatches(); - saveCurrentOrder(); - return true; -} - -QVariant MinecraftProfile::data(const QModelIndex &index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - int row = index.row(); - int column = index.column(); - - if (row < 0 || row >= m_patches.size()) - return QVariant(); - - auto patch = m_patches.at(row); - - if (role == Qt::DisplayRole) - { - switch (column) - { - case 0: - return m_patches.at(row)->getName(); - case 1: - { - if(patch->isCustom()) - { - return QString("%1 (Custom)").arg(patch->getVersion()); - } - else - { - return patch->getVersion(); - } - } - default: - return QVariant(); - } - } - if(role == Qt::DecorationRole) - { - switch(column) - { - case 0: - { - auto severity = patch->getProblemSeverity(); - switch (severity) - { - case ProblemSeverity::Warning: - return "warning"; - case ProblemSeverity::Error: - return "error"; - default: - return QVariant(); - } - } - default: - { - return QVariant(); - } - } - } - return QVariant(); -} -QVariant MinecraftProfile::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (orientation == Qt::Horizontal) - { - if (role == Qt::DisplayRole) - { - switch (section) - { - case 0: - return tr("Name"); - case 1: - return tr("Version"); - default: - return QVariant(); - } - } - } - return QVariant(); -} -Qt::ItemFlags MinecraftProfile::flags(const QModelIndex &index) const -{ - if (!index.isValid()) - return Qt::NoItemFlags; - return Qt::ItemIsSelectable | Qt::ItemIsEnabled; -} - -int MinecraftProfile::rowCount(const QModelIndex &parent) const -{ - return m_patches.size(); -} - -int MinecraftProfile::columnCount(const QModelIndex &parent) const -{ - return 2; -} - -void MinecraftProfile::saveCurrentOrder() const -{ - ProfileUtils::PatchOrder order; - for(auto item: m_patches) - { - if(!item->isMoveable()) - continue; - order.append(item->getID()); - } - saveOrder_internal(order); -} - -void MinecraftProfile::move(const int index, const MoveDirection direction) -{ - int theirIndex; - if (direction == MoveUp) - { - theirIndex = index - 1; - } - else - { - theirIndex = index + 1; - } - - if (index < 0 || index >= m_patches.size()) - return; - if (theirIndex >= rowCount()) - theirIndex = rowCount() - 1; - if (theirIndex == -1) - theirIndex = rowCount() - 1; - if (index == theirIndex) - return; - int togap = theirIndex > index ? theirIndex + 1 : theirIndex; - - auto from = versionPatch(index); - auto to = versionPatch(theirIndex); - - if (!from || !to || !to->isMoveable() || !from->isMoveable()) - { - return; - } - beginMoveRows(QModelIndex(), index, index, QModelIndex(), togap); - m_patches.swap(index, theirIndex); - endMoveRows(); - reapplyPatches(); - saveCurrentOrder(); -} -void MinecraftProfile::resetOrder() -{ - resetOrder_internal(); - reload(); -} - -bool MinecraftProfile::reapplyPatches() -{ - try - { - clear(); - for(auto file: m_patches) - { - qDebug() << "Applying" << file->getID() << (file->getProblemSeverity() == ProblemSeverity::Error ? "ERROR" : "GOOD"); - file->applyTo(this); - } - } - catch (Exception & error) - { - clear(); - qWarning() << "Couldn't apply profile patches because: " << error.cause(); - return false; - } - return true; -} - -static void applyString(const QString & from, QString & to) -{ - if(from.isEmpty()) - return; - to = from; -} - -void MinecraftProfile::applyMinecraftVersion(const QString& id) -{ - applyString(id, this->m_minecraftVersion); -} - -void MinecraftProfile::applyAppletClass(const QString& appletClass) -{ - applyString(appletClass, this->m_appletClass); -} - -void MinecraftProfile::applyMainClass(const QString& mainClass) -{ - applyString(mainClass, this->m_mainClass); -} - -void MinecraftProfile::applyMinecraftArguments(const QString& minecraftArguments) -{ - applyString(minecraftArguments, this->m_minecraftArguments); -} - -void MinecraftProfile::applyMinecraftVersionType(const QString& type) -{ - applyString(type, this->m_minecraftVersionType); -} - -void MinecraftProfile::applyMinecraftAssets(MojangAssetIndexInfo::Ptr assets) -{ - if(assets) - { - m_minecraftAssets = assets; - } -} - -void MinecraftProfile::applyTraits(const QSet& traits) -{ - this->m_traits.unite(traits); -} - -void MinecraftProfile::applyTweakers(const QStringList& tweakers) -{ - // if the applied tweakers override an existing one, skip it. this effectively moves it later in the sequence - QStringList newTweakers; - for(auto & tweaker: m_tweakers) - { - if (tweakers.contains(tweaker)) - { - continue; - } - newTweakers.append(tweaker); - } - // then just append the new tweakers (or moved original ones) - newTweakers += tweakers; - m_tweakers = newTweakers; -} - -void MinecraftProfile::applyJarMods(const QList& jarMods) -{ - this->m_jarMods.append(jarMods); -} - -static int findLibraryByName(QList *haystack, const GradleSpecifier &needle) -{ - int retval = -1; - for (int i = 0; i < haystack->size(); ++i) - { - if (haystack->at(i)->rawName().matchName(needle)) - { - // only one is allowed. - if (retval != -1) - return -1; - retval = i; - } - } - return retval; -} - -void MinecraftProfile::applyMods(const QList& mods) -{ - QList * list = &m_mods; - for(auto & mod: mods) - { - auto modCopy = Library::limitedCopy(mod); - - // find the mod by name. - const int index = findLibraryByName(list, mod->rawName()); - // mod not found? just add it. - if (index < 0) - { - list->append(modCopy); - return; - } - - auto existingLibrary = list->at(index); - // if we are higher it means we should update - if (Version(mod->version()) > Version(existingLibrary->version())) - { - list->replace(index, modCopy); - } - } -} - -void MinecraftProfile::applyLibrary(LibraryPtr library) -{ - if(!library->isActive()) - { - return; - } - - QList * list = &m_libraries; - if(library->isNative()) - { - list = &m_nativeLibraries; - } - - auto libraryCopy = Library::limitedCopy(library); - - // find the library by name. - const int index = findLibraryByName(list, library->rawName()); - // library not found? just add it. - if (index < 0) - { - list->append(libraryCopy); - return; - } - - auto existingLibrary = list->at(index); - // if we are higher it means we should update - if (Version(library->version()) > Version(existingLibrary->version())) - { - list->replace(index, libraryCopy); - } -} - -const LibraryPtr MinecraftProfile::getMainJar() const -{ - return m_mainJar; -} - -void MinecraftProfile::applyMainJar(LibraryPtr jar) -{ - if(jar) - { - m_mainJar = jar; - } -} - -void MinecraftProfile::applyProblemSeverity(ProblemSeverity severity) -{ - if (m_problemSeverity < severity) - { - m_problemSeverity = severity; - } -} - - -QString MinecraftProfile::getMinecraftVersion() const -{ - return m_minecraftVersion; -} - -QString MinecraftProfile::getAppletClass() const -{ - return m_appletClass; -} - -QString MinecraftProfile::getMainClass() const -{ - return m_mainClass; -} - -const QSet &MinecraftProfile::getTraits() const -{ - return m_traits; -} - -const QStringList & MinecraftProfile::getTweakers() const -{ - return m_tweakers; -} - -bool MinecraftProfile::hasTrait(const QString& trait) const -{ - return m_traits.contains(trait); -} - -ProblemSeverity MinecraftProfile::getProblemSeverity() const -{ - return m_problemSeverity; -} - -QString MinecraftProfile::getMinecraftVersionType() const -{ - return m_minecraftVersionType; -} - -std::shared_ptr MinecraftProfile::getMinecraftAssets() const -{ - if(!m_minecraftAssets) - { - return std::make_shared("legacy"); - } - return m_minecraftAssets; -} - -QString MinecraftProfile::getMinecraftArguments() const -{ - return m_minecraftArguments; -} - -const QList & MinecraftProfile::getJarMods() const -{ - return m_jarMods; -} - -const QList & MinecraftProfile::getLibraries() const -{ - return m_libraries; -} - -const QList & MinecraftProfile::getNativeLibraries() const -{ - return m_nativeLibraries; -} - -void MinecraftProfile::getLibraryFiles(const QString& architecture, QStringList& jars, QStringList& nativeJars, const QString& overridePath, const QString& tempPath) const -{ - QStringList native32, native64; - jars.clear(); - nativeJars.clear(); - for (auto lib : getLibraries()) - { - lib->getApplicableFiles(currentSystem, jars, nativeJars, native32, native64, overridePath); - } - // NOTE: order is important here, add main jar last to the lists - if(m_mainJar) - { - // FIXME: HACK!! jar modding is weird and unsystematic! - if(m_jarMods.size()) - { - QDir tempDir(tempPath); - jars.append(tempDir.absoluteFilePath("minecraft.jar")); - } - else - { - m_mainJar->getApplicableFiles(currentSystem, jars, nativeJars, native32, native64, overridePath); - } - } - for (auto lib : getNativeLibraries()) - { - lib->getApplicableFiles(currentSystem, jars, nativeJars, native32, native64, overridePath); - } - if(architecture == "32") - { - nativeJars.append(native32); - } - else if(architecture == "64") - { - nativeJars.append(native64); - } -} - -void MinecraftProfile::installJarMods(QStringList selectedFiles) -{ - installJarMods_internal(selectedFiles); -} - -void MinecraftProfile::installCustomJar(QString selectedFile) -{ - installCustomJar_internal(selectedFile); -} - - -/* - * TODO: get rid of this. Get rid of all order numbers. - */ -int MinecraftProfile::getFreeOrderNumber() -{ - int largest = 100; - // yes, I do realize this is dumb. The order thing itself is dumb. and to be removed next. - for(auto thing: m_patches) - { - int order = thing->getOrder(); - if(order > largest) - largest = order; - } - return largest + 1; -} - -void MinecraftProfile::upgradeDeprecatedFiles_internal() -{ - auto versionJsonPath = FS::PathCombine(m_instance->instanceRoot(), "version.json"); - auto customJsonPath = FS::PathCombine(m_instance->instanceRoot(), "custom.json"); - auto mcJson = FS::PathCombine(m_instance->instanceRoot(), "patches" , "net.minecraft.json"); - - QString sourceFile; - QString renameFile; - - // convert old crap. - if(QFile::exists(customJsonPath)) - { - sourceFile = customJsonPath; - renameFile = versionJsonPath; - } - else if(QFile::exists(versionJsonPath)) - { - sourceFile = versionJsonPath; - } - if(!sourceFile.isEmpty() && !QFile::exists(mcJson)) - { - if(!FS::ensureFilePathExists(mcJson)) - { - qWarning() << "Couldn't create patches folder for" << m_instance->name(); - return; - } - if(!renameFile.isEmpty() && QFile::exists(renameFile)) - { - if(!QFile::rename(renameFile, renameFile + ".old")) - { - qWarning() << "Couldn't rename" << renameFile << "to" << renameFile + ".old" << "in" << m_instance->name(); - return; - } - } - auto file = ProfileUtils::parseJsonFile(QFileInfo(sourceFile), false); - ProfileUtils::removeLwjglFromPatch(file); - file->uid = "net.minecraft"; - file->version = file->minecraftVersion; - file->name = "Minecraft"; - auto data = OneSixVersionFormat::versionFileToJson(file, false).toJson(); - QSaveFile newPatchFile(mcJson); - if(!newPatchFile.open(QIODevice::WriteOnly)) - { - newPatchFile.cancelWriting(); - qWarning() << "Couldn't open main patch for writing in" << m_instance->name(); - return; - } - newPatchFile.write(data); - if(!newPatchFile.commit()) - { - qWarning() << "Couldn't save main patch in" << m_instance->name(); - return; - } - if(!QFile::rename(sourceFile, sourceFile + ".old")) - { - qWarning() << "Couldn't rename" << sourceFile << "to" << sourceFile + ".old" << "in" << m_instance->name(); - return; - } - } -} - -void MinecraftProfile::loadDefaultBuiltinPatches_internal() -{ - auto addBuiltinPatch = [&](const QString &uid, const QString intendedVersion, int order) - { - auto jsonFilePath = FS::PathCombine(m_instance->instanceRoot(), "patches" , uid + ".json"); - // load up the base minecraft patch - ProfilePatchPtr profilePatch; - if(QFile::exists(jsonFilePath)) - { - auto file = ProfileUtils::parseJsonFile(QFileInfo(jsonFilePath), false); - if(file->version.isEmpty()) - { - file->version = intendedVersion; - } - profilePatch = std::make_shared(file, jsonFilePath); - profilePatch->setVanilla(false); - profilePatch->setRevertible(true); - } - else - { - auto metaVersion = ENV.metadataIndex()->get(uid, intendedVersion); - profilePatch = std::make_shared(metaVersion); - profilePatch->setVanilla(true); - } - profilePatch->setOrder(order); - appendPatch(profilePatch); - }; - addBuiltinPatch("net.minecraft", m_instance->getComponentVersion("net.minecraft"), -2); - addBuiltinPatch("org.lwjgl", m_instance->getComponentVersion("org.lwjgl"), -1); -} - -void MinecraftProfile::loadUserPatches_internal() -{ - // first, collect all patches (that are not builtins of OneSix) and load them - QMap loadedPatches; - QDir patchesDir(FS::PathCombine(m_instance->instanceRoot(),"patches")); - for (auto info : patchesDir.entryInfoList(QStringList() << "*.json", QDir::Files)) - { - // 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(file, info.filePath()); - patch->setRemovable(true); - patch->setMovable(true); - if(ENV.metadataIndex()->hasUid(file->uid)) - { - // FIXME: requesting a uid/list creates it in the index... this allows reverting to possibly invalid versions... - patch->setRevertible(true); - } - 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)) - { - auto patch = std::make_shared(ENV.metadataIndex()->get(uid, patchVersion)); - patch->setOrder(order); - patch->setVanilla(true); - patch->setRemovable(true); - patch->setMovable(true); - loadedPatches[uid] = patch; - } - }; - loadSpecial("net.minecraftforge", 5); - loadSpecial("com.mumfrey.liteloader", 10); - - // now add all the patches by user sort order - ProfileUtils::PatchOrder userOrder; - ProfileUtils::readOverrideOrders(FS::PathCombine(m_instance->instanceRoot(), "order.json"), userOrder); - for (auto uid : userOrder) - { - // ignore builtins - if (uid == "net.minecraft") - continue; - if (uid == "org.lwjgl") - continue; - // ordering has a patch that is gone? - if(!loadedPatches.contains(uid)) - { - continue; - } - appendPatch(loadedPatches.take(uid)); - } - - // is there anything left to sort? - if(loadedPatches.isEmpty()) - { - // TODO: save the order here? - return; - } - - // inserting into multimap by order number as key sorts the patches and detects duplicates - QMultiMap files; - auto iter = loadedPatches.begin(); - while(iter != loadedPatches.end()) - { - files.insert((*iter)->getOrder(), *iter); - iter++; - } - - // then just extract the patches and put them in the list - for (auto order : files.keys()) - { - const auto &values = files.values(order); - for(auto &value: values) - { - // TODO: put back the insertion of problem messages here, so the user knows about the id duplication - appendPatch(value); - } - } - // TODO: save the order here? -} - - -void MinecraftProfile::load_internal() -{ - clearPatches(); - upgradeDeprecatedFiles_internal(); - loadDefaultBuiltinPatches_internal(); - loadUserPatches_internal(); -} - -bool MinecraftProfile::saveOrder_internal(ProfileUtils::PatchOrder order) const -{ - return ProfileUtils::writeOverrideOrders(FS::PathCombine(m_instance->instanceRoot(), "order.json"), order); -} - -bool MinecraftProfile::resetOrder_internal() -{ - return QDir(m_instance->instanceRoot()).remove("order.json"); -} - -bool MinecraftProfile::removePatch_internal(ProfilePatchPtr patch) -{ - bool ok = true; - // first, remove the patch file. this ensures it's not used anymore - auto fileName = patch->getFilename(); - if(fileName.size()) - { - QFile patchFile(fileName); - if(patchFile.exists() && !patchFile.remove()) - { - qCritical() << "File" << fileName << "could not be removed because:" << patchFile.errorString(); - return false; - } - } - if(!m_instance->getComponentVersion(patch->getID()).isEmpty()) - { - m_instance->setComponentVersion(patch->getID(), QString()); - } - - // FIXME: we need a generic way of removing local resources, not just jar mods... - auto preRemoveJarMod = [&](LibraryPtr jarMod) -> bool - { - if (!jarMod->isLocal()) - { - return true; - } - QStringList jar, temp1, temp2, temp3; - jarMod->getApplicableFiles(currentSystem, jar, temp1, temp2, temp3, m_instance->jarmodsPath().absolutePath()); - QFileInfo finfo (jar[0]); - if(finfo.exists()) - { - QFile jarModFile(jar[0]); - if(!jarModFile.remove()) - { - qCritical() << "File" << jar[0] << "could not be removed because:" << jarModFile.errorString(); - return false; - } - return true; - } - return true; - }; - - auto &jarMods = patch->getVersionFile()->jarMods; - for(auto &jarmod: jarMods) - { - ok &= preRemoveJarMod(jarmod); - } - return ok; -} - -bool MinecraftProfile::customizePatch_internal(ProfilePatchPtr patch) -{ - if(patch->isCustom()) - { - return false; - } - - auto filename = FS::PathCombine(m_instance->instanceRoot(), "patches" , patch->getID() + ".json"); - if(!FS::ensureFilePathExists(filename)) - { - return false; - } - // FIXME: get rid of this try-catch. - try - { - QSaveFile jsonFile(filename); - if(!jsonFile.open(QIODevice::WriteOnly)) - { - return false; - } - auto vfile = patch->getVersionFile(); - if(!vfile) - { - return false; - } - auto document = OneSixVersionFormat::versionFileToJson(vfile, true); - jsonFile.write(document.toJson()); - if(!jsonFile.commit()) - { - return false; - } - load_internal(); - } - catch (Exception &error) - { - qWarning() << "Version could not be loaded:" << error.cause(); - } - return true; -} - -bool MinecraftProfile::revertPatch_internal(ProfilePatchPtr patch) -{ - if(!patch->isCustom()) - { - // already not custom - return true; - } - auto filename = patch->getFilename(); - if(!QFile::exists(filename)) - { - // already gone / not custom - return true; - } - // just kill the file and reload - bool result = QFile::remove(filename); - // FIXME: get rid of this try-catch. - try - { - load_internal(); - } - catch (Exception &error) - { - qWarning() << "Version could not be loaded:" << error.cause(); - } - return result; -} - -bool MinecraftProfile::installJarMods_internal(QStringList filepaths) -{ - QString patchDir = FS::PathCombine(m_instance->instanceRoot(), "patches"); - if(!FS::ensureFolderPathExists(patchDir)) - { - return false; - } - - if (!FS::ensureFolderPathExists(m_instance->jarModsDir())) - { - return false; - } - - for(auto filepath:filepaths) - { - QFileInfo sourceInfo(filepath); - auto uuid = QUuid::createUuid(); - QString id = uuid.toString().remove('{').remove('}'); - QString target_filename = id + ".jar"; - QString target_id = "org.multimc.jarmod." + id; - QString target_name = sourceInfo.completeBaseName() + " (jar mod)"; - QString finalPath = FS::PathCombine(m_instance->jarModsDir(), target_filename); - - QFileInfo targetInfo(finalPath); - if(targetInfo.exists()) - { - return false; - } - - if (!QFile::copy(sourceInfo.absoluteFilePath(),QFileInfo(finalPath).absoluteFilePath())) - { - return false; - } - - auto f = std::make_shared(); - auto jarMod = std::make_shared(); - jarMod->setRawName(GradleSpecifier("org.multimc.jarmods:" + id + ":1")); - jarMod->setFilename(target_filename); - jarMod->setDisplayName(sourceInfo.completeBaseName()); - jarMod->setHint("local"); - f->jarMods.append(jarMod); - f->name = target_name; - f->uid = target_id; - f->order = getFreeOrderNumber(); - QString patchFileName = FS::PathCombine(patchDir, target_id + ".json"); - - QFile file(patchFileName); - if (!file.open(QFile::WriteOnly)) - { - qCritical() << "Error opening" << file.fileName() - << "for reading:" << file.errorString(); - return false; - } - file.write(OneSixVersionFormat::versionFileToJson(f, true).toJson()); - file.close(); - - auto patch = std::make_shared(f, patchFileName); - patch->setMovable(true); - patch->setRemovable(true); - appendPatch(patch); - } - saveCurrentOrder(); - reapplyPatches(); - return true; -} - -bool MinecraftProfile::installCustomJar_internal(QString filepath) -{ - QString patchDir = FS::PathCombine(m_instance->instanceRoot(), "patches"); - if(!FS::ensureFolderPathExists(patchDir)) - { - return false; - } - - QString libDir = m_instance->getLocalLibraryPath(); - if (!FS::ensureFolderPathExists(libDir)) - { - return false; - } - - auto specifier = GradleSpecifier("org.multimc:customjar:1"); - QFileInfo sourceInfo(filepath); - QString target_filename = specifier.getFileName(); - QString target_id = specifier.artifactId(); - QString target_name = sourceInfo.completeBaseName() + " (custom jar)"; - QString finalPath = FS::PathCombine(libDir, target_filename); - - QFileInfo jarInfo(finalPath); - if (jarInfo.exists()) - { - if(!QFile::remove(finalPath)) - { - return false; - } - } - if (!QFile::copy(filepath, finalPath)) - { - return false; - } - - auto f = std::make_shared(); - auto jarMod = std::make_shared(); - jarMod->setRawName(specifier); - jarMod->setDisplayName(sourceInfo.completeBaseName()); - jarMod->setHint("local"); - f->mainJar = jarMod; - f->name = target_name; - f->uid = target_id; - f->order = getFreeOrderNumber(); - QString patchFileName = FS::PathCombine(patchDir, target_id + ".json"); - - QFile file(patchFileName); - if (!file.open(QFile::WriteOnly)) - { - qCritical() << "Error opening" << file.fileName() - << "for reading:" << file.errorString(); - return false; - } - file.write(OneSixVersionFormat::versionFileToJson(f, true).toJson()); - file.close(); - - auto patch = std::make_shared(f, patchFileName); - patch->setMovable(true); - patch->setRemovable(true); - appendPatch(patch); - - saveCurrentOrder(); - reapplyPatches(); - return true; -} \ No newline at end of file diff --git a/api/logic/minecraft/MinecraftProfile.h b/api/logic/minecraft/MinecraftProfile.h deleted file mode 100644 index da8dcbbc..00000000 --- a/api/logic/minecraft/MinecraftProfile.h +++ /dev/null @@ -1,203 +0,0 @@ -/* Copyright 2013-2017 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 - -#include -#include -#include - -#include "Library.h" -#include "ProfilePatch.h" -#include "ProfileUtils.h" -#include "BaseVersion.h" -#include "MojangDownloadInfo.h" - -#include "multimc_logic_export.h" - -class MinecraftInstance; - - -class MULTIMC_LOGIC_EXPORT MinecraftProfile : public QAbstractListModel -{ - Q_OBJECT - -public: - explicit MinecraftProfile(MinecraftInstance * instance); - virtual ~MinecraftProfile(); - - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; - virtual int columnCount(const QModelIndex &parent) const override; - virtual Qt::ItemFlags flags(const QModelIndex &index) const override; - - /// is this version unchanged by the user? - bool isVanilla(); - - /// remove any customizations on top of whatever 'vanilla' means - bool revertToVanilla(); - - /// install more jar mods - void installJarMods(QStringList selectedFiles); - - /// install more jar mods - void installCustomJar(QString selectedFile); - - /// DEPRECATED, remove ASAP - int getFreeOrderNumber(); - - enum MoveDirection { MoveUp, MoveDown }; - /// move patch file # up or down the list - void move(const int index, const MoveDirection direction); - - /// remove patch file # - including files/records - bool remove(const int index); - - /// remove patch file by id - including files/records - bool remove(const QString id); - - bool customize(int index); - - bool revertToBase(int index); - - void resetOrder(); - - /// reload all profile patches from storage, clear the profile and apply the patches - void reload(); - - /// clear the profile - void clear(); - - /// apply the patches. Catches all the errors and returns true/false for success/failure - bool reapplyPatches(); - -public: /* application of profile variables from patches */ - void applyMinecraftVersion(const QString& id); - void applyMainClass(const QString& mainClass); - void applyAppletClass(const QString& appletClass); - void applyMinecraftArguments(const QString& minecraftArguments); - void applyMinecraftVersionType(const QString& type); - void applyMinecraftAssets(MojangAssetIndexInfo::Ptr assets); - void applyTraits(const QSet &traits); - void applyTweakers(const QStringList &tweakers); - void applyJarMods(const QList &jarMods); - void applyMods(const QList &jarMods); - void applyLibrary(LibraryPtr library); - void applyMainJar(LibraryPtr jar); - void applyProblemSeverity(ProblemSeverity severity); - -public: /* getters for profile variables */ - QString getMinecraftVersion() const; - QString getMainClass() const; - QString getAppletClass() const; - QString getMinecraftVersionType() const; - MojangAssetIndexInfo::Ptr getMinecraftAssets() const; - QString getMinecraftArguments() const; - const QSet & getTraits() const; - const QStringList & getTweakers() const; - const QList & getJarMods() const; - const QList & getLibraries() const; - const QList & getNativeLibraries() const; - const LibraryPtr getMainJar() const; - void getLibraryFiles(const QString & architecture, QStringList & jars, QStringList & nativeJars, const QString & overridePath, - const QString & tempPath) const; - bool hasTrait(const QString & trait) const; - ProblemSeverity getProblemSeverity() const; - -public: - /// get the profile patch by id - ProfilePatchPtr versionPatch(const QString &id); - - /// get the profile patch by index - ProfilePatchPtr versionPatch(int index); - - /// save the current patch order - void saveCurrentOrder() const; - - /// Remove all the patches - void clearPatches(); - - /// Add the patch object to the internal list of patches - void appendPatch(ProfilePatchPtr patch); - -private: - void load_internal(); - bool resetOrder_internal(); - bool saveOrder_internal(ProfileUtils::PatchOrder order) const; - bool installJarMods_internal(QStringList filepaths); - bool installCustomJar_internal(QString filepath); - bool removePatch_internal(ProfilePatchPtr patch); - bool customizePatch_internal(ProfilePatchPtr patch); - bool revertPatch_internal(ProfilePatchPtr patch); - void loadDefaultBuiltinPatches_internal(); - void loadUserPatches_internal(); - void upgradeDeprecatedFiles_internal(); - -private: /* data */ - /// the version of Minecraft - jar to use - QString m_minecraftVersion; - - /// Release type - "release" or "snapshot" - QString m_minecraftVersionType; - - /// Assets type - "legacy" or a version ID - MojangAssetIndexInfo::Ptr m_minecraftAssets; - - /** - * 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 m_minecraftArguments; - - /// A list of all tweaker classes - QStringList m_tweakers; - - /// The main class to load first - QString m_mainClass; - - /// The applet class, for some very old minecraft releases - QString m_appletClass; - - /// the list of libraries - QList m_libraries; - - /// the main jar - LibraryPtr m_mainJar; - - /// the list of libraries - QList m_nativeLibraries; - - /// traits, collected from all the version files (version files can only add) - QSet m_traits; - - /// A list of jar mods. version files can add those. - QList m_jarMods; - - /// the list of mods - QList m_mods; - - ProblemSeverity m_problemSeverity = ProblemSeverity::None; - - /// list of attached profile patches - QList m_patches; - - // the instance this belongs to - MinecraftInstance *m_instance; -}; diff --git a/api/logic/minecraft/MinecraftUpdate.cpp b/api/logic/minecraft/MinecraftUpdate.cpp index 61dce779..529cf13e 100644 --- a/api/logic/minecraft/MinecraftUpdate.cpp +++ b/api/logic/minecraft/MinecraftUpdate.cpp @@ -24,7 +24,7 @@ #include #include "BaseInstance.h" -#include "minecraft/MinecraftProfile.h" +#include "minecraft/ComponentList.h" #include "minecraft/Library.h" #include "net/URLConstants.h" #include @@ -52,7 +52,7 @@ OneSixUpdate::OneSixUpdate(MinecraftInstance *inst, QObject *parent) : Task(pare * We should not rely on the remote to be there... and prefer local files if it does not respond. */ qDebug() << "Updating patches..."; - auto profile = m_inst->getMinecraftProfile(); + auto profile = m_inst->getComponentList(); m_inst->reloadProfile(); for(int i = 0; i < profile->rowCount(); i++) { diff --git a/api/logic/minecraft/OneSixVersionFormat.h b/api/logic/minecraft/OneSixVersionFormat.h index 64f18da8..2306ac8e 100644 --- a/api/logic/minecraft/OneSixVersionFormat.h +++ b/api/logic/minecraft/OneSixVersionFormat.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include diff --git a/api/logic/minecraft/ProfilePatch.cpp b/api/logic/minecraft/ProfilePatch.cpp index 049463ac..b8b5c240 100644 --- a/api/logic/minecraft/ProfilePatch.cpp +++ b/api/logic/minecraft/ProfilePatch.cpp @@ -5,7 +5,7 @@ #include "meta/Version.h" #include "VersionFile.h" -#include "minecraft/MinecraftProfile.h" +#include "minecraft/ComponentList.h" ProfilePatch::ProfilePatch(std::shared_ptr version) :m_metaVersion(version) @@ -22,7 +22,7 @@ std::shared_ptr ProfilePatch::getMeta() return m_metaVersion; } -void ProfilePatch::applyTo(MinecraftProfile* profile) +void ProfilePatch::applyTo(ComponentList* profile) { auto vfile = getVersionFile(); if(vfile) diff --git a/api/logic/minecraft/ProfilePatch.h b/api/logic/minecraft/ProfilePatch.h index 59171a0a..af5e89a4 100644 --- a/api/logic/minecraft/ProfilePatch.h +++ b/api/logic/minecraft/ProfilePatch.h @@ -6,7 +6,7 @@ #include #include "ProblemProvider.h" -class MinecraftProfile; +class ComponentList; namespace Meta { class Version; @@ -21,7 +21,7 @@ public: ProfilePatch(std::shared_ptr file, const QString &filename = QString()); virtual ~ProfilePatch(){}; - virtual void applyTo(MinecraftProfile *profile); + virtual void applyTo(ComponentList *profile); virtual bool isMoveable(); virtual bool isCustomizable(); diff --git a/api/logic/minecraft/VersionFile.cpp b/api/logic/minecraft/VersionFile.cpp index 85989549..65675873 100644 --- a/api/logic/minecraft/VersionFile.cpp +++ b/api/logic/minecraft/VersionFile.cpp @@ -5,7 +5,7 @@ #include "minecraft/VersionFile.h" #include "minecraft/Library.h" -#include "minecraft/MinecraftProfile.h" +#include "minecraft/ComponentList.h" #include "ParseUtils.h" #include @@ -15,7 +15,7 @@ static bool isMinecraftVersion(const QString &uid) return uid == "net.minecraft"; } -void VersionFile::applyTo(MinecraftProfile *profile) +void VersionFile::applyTo(ComponentList *profile) { // Only real Minecraft can set those. Don't let anything override them. if (isMinecraftVersion(uid)) diff --git a/api/logic/minecraft/VersionFile.h b/api/logic/minecraft/VersionFile.h index e3fb46ed..001b696c 100644 --- a/api/logic/minecraft/VersionFile.h +++ b/api/logic/minecraft/VersionFile.h @@ -11,7 +11,7 @@ #include "ProblemProvider.h" #include "Library.h" -class MinecraftProfile; +class ComponentList; class VersionFile; struct MojangDownloadInfo; struct MojangAssetIndexInfo; @@ -22,7 +22,7 @@ class VersionFile : public ProblemContainer friend class MojangVersionFormat; friend class OneSixVersionFormat; public: /* methods */ - void applyTo(MinecraftProfile *profile); + void applyTo(ComponentList *profile); public: /* data */ /// MultiMC: order hint for this version file if no explicit order is set diff --git a/api/logic/minecraft/launch/ModMinecraftJar.cpp b/api/logic/minecraft/launch/ModMinecraftJar.cpp index 497a9d2d..14b00447 100644 --- a/api/logic/minecraft/launch/ModMinecraftJar.cpp +++ b/api/logic/minecraft/launch/ModMinecraftJar.cpp @@ -19,7 +19,7 @@ #include "minecraft/OpSys.h" #include "FileSystem.h" #include "minecraft/MinecraftInstance.h" -#include "minecraft/MinecraftProfile.h" +#include "minecraft/ComponentList.h" void ModMinecraftJar::executeTask() { @@ -42,7 +42,7 @@ void ModMinecraftJar::executeTask() } // create temporary modded jar, if needed - auto profile = m_inst->getMinecraftProfile(); + auto profile = m_inst->getComponentList(); auto jarMods = m_inst->getJarMods(); if(jarMods.size()) { diff --git a/api/logic/minecraft/legacy/LegacyUpgradeTask.cpp b/api/logic/minecraft/legacy/LegacyUpgradeTask.cpp index e41d87cb..fab48005 100644 --- a/api/logic/minecraft/legacy/LegacyUpgradeTask.cpp +++ b/api/logic/minecraft/legacy/LegacyUpgradeTask.cpp @@ -7,7 +7,7 @@ #include #include "LegacyInstance.h" #include "minecraft/MinecraftInstance.h" -#include "minecraft/MinecraftProfile.h" +#include "minecraft/ComponentList.h" #include "classparser.h" LegacyUpgradeTask::LegacyUpgradeTask(SettingsObjectPtr settings, const QString & stagingPath, InstancePtr origInstance, const QString & newName) @@ -90,7 +90,7 @@ void LegacyUpgradeTask::copyFinished() // BUG: reloadProfile should not be necessary, but setComponentVersion voids the profile created by init()! inst->reloadProfile(); - auto profile = inst->getMinecraftProfile(); + auto profile = inst->getComponentList(); if(legacyInst->shouldUseCustomBaseJar()) { diff --git a/api/logic/minecraft/update/AssetUpdateTask.cpp b/api/logic/minecraft/update/AssetUpdateTask.cpp index b67e630e..6919e0a6 100644 --- a/api/logic/minecraft/update/AssetUpdateTask.cpp +++ b/api/logic/minecraft/update/AssetUpdateTask.cpp @@ -1,7 +1,7 @@ #include "Env.h" #include "AssetUpdateTask.h" #include "minecraft/MinecraftInstance.h" -#include "minecraft/MinecraftProfile.h" +#include "minecraft/ComponentList.h" #include "net/ChecksumValidator.h" #include "minecraft/AssetsUtils.h" @@ -12,7 +12,7 @@ AssetUpdateTask::AssetUpdateTask(MinecraftInstance * inst) void AssetUpdateTask::executeTask() { setStatus(tr("Updating assets index...")); - auto profile = m_inst->getMinecraftProfile(); + auto profile = m_inst->getComponentList(); auto assets = profile->getMinecraftAssets(); QUrl indexUrl = assets->url; QString localPath = assets->id + ".json"; @@ -48,7 +48,7 @@ void AssetUpdateTask::assetIndexFinished() AssetsIndex index; qDebug() << m_inst->name() << ": Finished asset index download"; - auto profile = m_inst->getMinecraftProfile(); + auto profile = m_inst->getComponentList(); auto assets = profile->getMinecraftAssets(); QString asset_fname = "assets/indexes/" + assets->id + ".json"; diff --git a/api/logic/minecraft/update/FMLLibrariesTask.cpp b/api/logic/minecraft/update/FMLLibrariesTask.cpp index 63428a48..e64b7a82 100644 --- a/api/logic/minecraft/update/FMLLibrariesTask.cpp +++ b/api/logic/minecraft/update/FMLLibrariesTask.cpp @@ -3,7 +3,7 @@ #include #include "FMLLibrariesTask.h" #include "minecraft/MinecraftInstance.h" -#include "minecraft/MinecraftProfile.h" +#include "minecraft/ComponentList.h" FMLLibrariesTask::FMLLibrariesTask(MinecraftInstance * inst) { @@ -13,7 +13,7 @@ void FMLLibrariesTask::executeTask() { // Get the mod list MinecraftInstance *inst = (MinecraftInstance *)m_inst; - std::shared_ptr profile = inst->getMinecraftProfile(); + std::shared_ptr profile = inst->getComponentList(); bool forge_present = false; if (!profile->hasTrait("legacyFML")) diff --git a/api/logic/minecraft/update/LibrariesTask.cpp b/api/logic/minecraft/update/LibrariesTask.cpp index c408f432..bbbd5f02 100644 --- a/api/logic/minecraft/update/LibrariesTask.cpp +++ b/api/logic/minecraft/update/LibrariesTask.cpp @@ -1,7 +1,7 @@ #include "Env.h" #include "LibrariesTask.h" #include "minecraft/MinecraftInstance.h" -#include "minecraft/MinecraftProfile.h" +#include "minecraft/ComponentList.h" LibrariesTask::LibrariesTask(MinecraftInstance * inst) { @@ -21,7 +21,7 @@ void LibrariesTask::executeTask() } // Build a list of URLs that will need to be downloaded. - std::shared_ptr profile = inst->getMinecraftProfile(); + std::shared_ptr profile = inst->getComponentList(); auto job = new NetJob(tr("Libraries for instance %1").arg(inst->name())); downloadJob.reset(job); diff --git a/application/pages/ModFolderPage.cpp b/application/pages/ModFolderPage.cpp index 422e1eb4..be1c8289 100644 --- a/application/pages/ModFolderPage.cpp +++ b/application/pages/ModFolderPage.cpp @@ -28,7 +28,7 @@ #include "minecraft/ModList.h" #include "minecraft/Mod.h" #include "minecraft/VersionFilterData.h" -#include "minecraft/MinecraftProfile.h" +#include "minecraft/ComponentList.h" #include ModFolderPage::ModFolderPage(BaseInstance *inst, std::shared_ptr mods, QString id, @@ -103,7 +103,7 @@ bool CoreModFolderPage::shouldDisplay() const auto inst = dynamic_cast(m_inst); if (!inst) return true; - auto version = inst->getMinecraftProfile(); + auto version = inst->getComponentList(); if (!version) return true; if(!version->versionPatch("net.minecraftforge")) diff --git a/application/pages/VersionPage.cpp b/application/pages/VersionPage.cpp index c915b42b..d65d6bc7 100644 --- a/application/pages/VersionPage.cpp +++ b/application/pages/VersionPage.cpp @@ -35,7 +35,7 @@ #include #include -#include "minecraft/MinecraftProfile.h" +#include "minecraft/ComponentList.h" #include "minecraft/auth/MojangAccountList.h" #include "minecraft/Mod.h" #include "icons/IconList.h" @@ -104,9 +104,9 @@ VersionPage::VersionPage(MinecraftInstance *inst, QWidget *parent) ui->setupUi(this); ui->tabWidget->tabBar()->hide(); - reloadMinecraftProfile(); + reloadComponentList(); - m_profile = m_inst->getMinecraftProfile(); + m_profile = m_inst->getComponentList(); if (m_profile) { auto proxy = new IconProxy(ui->packageView); @@ -192,7 +192,7 @@ void VersionPage::disableVersionControls() updateButtons(); } -bool VersionPage::reloadMinecraftProfile() +bool VersionPage::reloadComponentList() { try { @@ -215,7 +215,7 @@ bool VersionPage::reloadMinecraftProfile() void VersionPage::on_reloadBtn_clicked() { - reloadMinecraftProfile(); + reloadComponentList(); m_container->refreshContainer(); } @@ -230,7 +230,7 @@ void VersionPage::on_removeBtn_clicked() } } updateButtons(); - reloadMinecraftProfile(); + reloadComponentList(); m_container->refreshContainer(); } @@ -279,7 +279,7 @@ void VersionPage::on_moveUpBtn_clicked() { try { - m_profile->move(currentRow(), MinecraftProfile::MoveUp); + m_profile->move(currentRow(), ComponentList::MoveUp); } catch (Exception &e) { @@ -292,7 +292,7 @@ void VersionPage::on_moveDownBtn_clicked() { try { - m_profile->move(currentRow(), MinecraftProfile::MoveDown); + m_profile->move(currentRow(), ComponentList::MoveDown); } catch (Exception &e) { @@ -345,7 +345,7 @@ void VersionPage::on_changeVersionBtn_clicked() if (result != QMessageBox::Ok) return; m_profile->revertToVanilla(); - reloadMinecraftProfile(); + reloadComponentList(); } } m_inst->setComponentVersion(uid, vselect.selectedVersion()->descriptor()); diff --git a/application/pages/VersionPage.h b/application/pages/VersionPage.h index 0017be5c..0ac10a14 100644 --- a/application/pages/VersionPage.h +++ b/application/pages/VersionPage.h @@ -18,7 +18,7 @@ #include #include "minecraft/MinecraftInstance.h" -#include "minecraft/MinecraftProfile.h" +#include "minecraft/ComponentList.h" #include "BasePage.h" namespace Ui @@ -76,11 +76,11 @@ private: protected: /// FIXME: this shouldn't be necessary! - bool reloadMinecraftProfile(); + bool reloadComponentList(); private: Ui::VersionPage *ui; - std::shared_ptr m_profile; + std::shared_ptr m_profile; MinecraftInstance *m_inst; int currentIdx = 0; -- cgit v1.2.3