NOISSUE Add back Legacy for migration purposes
This commit is contained in:
		| @@ -228,6 +228,10 @@ set(MINECRAFT_SOURCES | ||||
| 	minecraft/launch/LauncherPartLaunch.h | ||||
| 	minecraft/launch/PrintInstanceInfo.cpp | ||||
| 	minecraft/launch/PrintInstanceInfo.h | ||||
| 	minecraft/legacy/LegacyModList.h | ||||
| 	minecraft/legacy/LegacyModList.cpp | ||||
| 	minecraft/legacy/LegacyInstance.h | ||||
| 	minecraft/legacy/LegacyInstance.cpp | ||||
| 	minecraft/GradleSpecifier.h | ||||
| 	minecraft/MinecraftInstance.cpp | ||||
| 	minecraft/MinecraftInstance.h | ||||
|   | ||||
| @@ -19,8 +19,6 @@ struct Env::Private | ||||
| 	shared_qobject_ptr<HttpMetaCache> m_metacache; | ||||
| 	std::shared_ptr<IIconList> m_iconlist; | ||||
| 	shared_qobject_ptr<Meta::Index> m_metadataIndex; | ||||
| 	// FIXME: replace with mojang format LWJGL in meta store | ||||
| 	std::shared_ptr<LWJGLVersionList> m_lwjgllist; | ||||
| 	QString m_jarsPath; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -13,7 +13,6 @@ class QNetworkAccessManager; | ||||
| class HttpMetaCache; | ||||
| class BaseVersionList; | ||||
| class BaseVersion; | ||||
| class LWJGLVersionList; | ||||
|  | ||||
| namespace Meta | ||||
| { | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
| #include "settings/INISettingsObject.h" | ||||
| #include "FileSystem.h" | ||||
| #include "minecraft/MinecraftInstance.h" | ||||
| #include "minecraft/legacy/LegacyInstance.h" | ||||
| #include "NullInstance.h" | ||||
|  | ||||
| #include <QDir> | ||||
| @@ -90,6 +91,10 @@ InstancePtr FolderInstanceProvider::loadInstance(const InstanceId& id) | ||||
| 	{ | ||||
| 		inst.reset(new MinecraftInstance(m_globalSettings, instanceSettings, instanceRoot)); | ||||
| 	} | ||||
| 	else if (inst_type == "Legacy") | ||||
| 	{ | ||||
| 		inst.reset(new LegacyInstance(m_globalSettings, instanceSettings, instanceRoot)); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		inst.reset(new NullInstance(m_globalSettings, instanceSettings, instanceRoot)); | ||||
|   | ||||
| @@ -24,6 +24,7 @@ | ||||
|  | ||||
| #include "multimc_logic_export.h" | ||||
|  | ||||
| class LegacyInstance; | ||||
| class BaseInstance; | ||||
| class QFileSystemWatcher; | ||||
|  | ||||
|   | ||||
							
								
								
									
										313
									
								
								api/logic/minecraft/legacy/LegacyInstance.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										313
									
								
								api/logic/minecraft/legacy/LegacyInstance.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,313 @@ | ||||
| /* 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 <QFileInfo> | ||||
| #include <minecraft/launch/LauncherPartLaunch.h> | ||||
| #include <QDir> | ||||
| #include <settings/Setting.h> | ||||
|  | ||||
| #include "LegacyInstance.h" | ||||
|  | ||||
| #include "minecraft/legacy/LegacyModList.h" | ||||
| #include "minecraft/ModList.h" | ||||
| #include "minecraft/WorldList.h" | ||||
| #include <MMCZip.h> | ||||
| #include <FileSystem.h> | ||||
|  | ||||
| LegacyInstance::LegacyInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir) | ||||
| 	: BaseInstance(globalSettings, settings, rootDir) | ||||
| { | ||||
| 	settings->registerSetting("NeedsRebuild", true); | ||||
| 	settings->registerSetting("ShouldUpdate", false); | ||||
| 	settings->registerSetting("JarVersion", "Unknown"); | ||||
| 	settings->registerSetting("IntendedJarVersion", ""); | ||||
| 	/* | ||||
| 	 * custom base jar has no default. it is determined in code... see the accessor methods for | ||||
| 	 *it | ||||
| 	 * | ||||
| 	 * for instances that DO NOT have the CustomBaseJar setting (legacy instances), | ||||
| 	 * [.]minecraft/bin/mcbackup.jar is the default base jar | ||||
| 	 */ | ||||
| 	settings->registerSetting("UseCustomBaseJar", true); | ||||
| 	settings->registerSetting("CustomBaseJar", ""); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::baseJar() const | ||||
| { | ||||
| 	bool customJar = m_settings->get("UseCustomBaseJar").toBool(); | ||||
| 	if (customJar) | ||||
| 	{ | ||||
| 		return customBaseJar(); | ||||
| 	} | ||||
| 	else | ||||
| 		return defaultBaseJar(); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::customBaseJar() const | ||||
| { | ||||
| 	QString value = m_settings->get("CustomBaseJar").toString(); | ||||
| 	if (value.isNull() || value.isEmpty()) | ||||
| 	{ | ||||
| 		return defaultCustomBaseJar(); | ||||
| 	} | ||||
| 	return value; | ||||
| } | ||||
|  | ||||
| bool LegacyInstance::shouldUseCustomBaseJar() const | ||||
| { | ||||
| 	return m_settings->get("UseCustomBaseJar").toBool(); | ||||
| } | ||||
|  | ||||
|  | ||||
| shared_qobject_ptr<Task> LegacyInstance::createUpdateTask() | ||||
| { | ||||
| 	return nullptr; | ||||
| } | ||||
|  | ||||
| /* | ||||
| class LegacyJarModTask : public Task | ||||
| { | ||||
| 	//Q_OBJECT | ||||
| public: | ||||
| 	explicit LegacyJarModTask(std::shared_ptr<LegacyInstance> inst) : Task(nullptr), m_inst(inst) | ||||
| 	{ | ||||
| 	} | ||||
| 	virtual void executeTask() | ||||
| 	{ | ||||
| 		if (!m_inst->shouldRebuild()) | ||||
| 		{ | ||||
| 			emitSucceeded(); | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		// Get the mod list | ||||
| 		auto modList = m_inst->getJarMods(); | ||||
|  | ||||
| 		QFileInfo runnableJar(m_inst->runnableJar()); | ||||
| 		QFileInfo baseJar(m_inst->baseJar()); | ||||
| 		bool base_is_custom = m_inst->shouldUseCustomBaseJar(); | ||||
|  | ||||
| 		// Nothing to do if there are no jar mods to install, no backup and just the mc jar | ||||
| 		if (base_is_custom) | ||||
| 		{ | ||||
| 			// yes, this can happen if the instance only has the runnable jar and not the base jar | ||||
| 			// it *could* be assumed that such an instance is vanilla, but that wouldn't be safe | ||||
| 			// because that's not something mmc4 guarantees | ||||
| 			if (runnableJar.isFile() && !baseJar.exists() && modList.empty()) | ||||
| 			{ | ||||
| 				m_inst->setShouldRebuild(false); | ||||
| 				emitSucceeded(); | ||||
| 				return; | ||||
| 			} | ||||
|  | ||||
| 			setStatus(tr("Installing mods: Backing up minecraft.jar ...")); | ||||
| 			if (!baseJar.exists() && !QFile::copy(runnableJar.filePath(), baseJar.filePath())) | ||||
| 			{ | ||||
| 				emitFailed("It seems both the active and base jar are gone. A fresh base jar will " | ||||
| 						"be used on next run."); | ||||
| 				m_inst->setShouldRebuild(true); | ||||
| 				m_inst->setShouldUpdate(true); | ||||
| 				m_inst->setShouldUseCustomBaseJar(false); | ||||
| 				return; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (!baseJar.exists()) | ||||
| 		{ | ||||
| 			emitFailed("The base jar " + baseJar.filePath() + " does not exist"); | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		if (runnableJar.exists() && !QFile::remove(runnableJar.filePath())) | ||||
| 		{ | ||||
| 			emitFailed("Failed to delete old minecraft.jar"); | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		setStatus(tr("Installing mods: Opening minecraft.jar ...")); | ||||
|  | ||||
| 		QString outputJarPath = runnableJar.filePath(); | ||||
| 		QString inputJarPath = baseJar.filePath(); | ||||
|  | ||||
| 		if(!MMCZip::createModdedJar(inputJarPath, outputJarPath, modList)) | ||||
| 		{ | ||||
| 			emitFailed(tr("Failed to create the custom Minecraft jar file.")); | ||||
| 			return; | ||||
| 		} | ||||
| 		m_inst->setShouldRebuild(false); | ||||
| 		// inst->UpdateVersion(true); | ||||
| 		emitSucceeded(); | ||||
| 		return; | ||||
|  | ||||
| 	} | ||||
| 	std::shared_ptr<LegacyInstance> m_inst; | ||||
| }; | ||||
| */ | ||||
|  | ||||
| std::shared_ptr<LegacyModList> LegacyInstance::jarModList() const | ||||
| { | ||||
| 	if (!jar_mod_list) | ||||
| 	{ | ||||
| 		auto list = new LegacyModList(jarModsDir(), modListFile()); | ||||
| 		jar_mod_list.reset(list); | ||||
| 	} | ||||
| 	jar_mod_list->update(); | ||||
| 	return jar_mod_list; | ||||
| } | ||||
|  | ||||
| QList<Mod> LegacyInstance::getJarMods() const | ||||
| { | ||||
| 	return jarModList()->allMods(); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::minecraftRoot() const | ||||
| { | ||||
| 	QFileInfo mcDir(FS::PathCombine(instanceRoot(), "minecraft")); | ||||
| 	QFileInfo dotMCDir(FS::PathCombine(instanceRoot(), ".minecraft")); | ||||
|  | ||||
| 	if (dotMCDir.exists() && !mcDir.exists()) | ||||
| 		return dotMCDir.filePath(); | ||||
| 	else | ||||
| 		return mcDir.filePath(); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::binRoot() const | ||||
| { | ||||
| 	return FS::PathCombine(minecraftRoot(), "bin"); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::jarModsDir() const | ||||
| { | ||||
| 	return FS::PathCombine(instanceRoot(), "instMods"); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::libDir() const | ||||
| { | ||||
| 	return FS::PathCombine(minecraftRoot(), "lib"); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::savesDir() const | ||||
| { | ||||
| 	return FS::PathCombine(minecraftRoot(), "saves"); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::loaderModsDir() const | ||||
| { | ||||
| 	return FS::PathCombine(minecraftRoot(), "mods"); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::coreModsDir() const | ||||
| { | ||||
| 	return FS::PathCombine(minecraftRoot(), "coremods"); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::resourceDir() const | ||||
| { | ||||
| 	return FS::PathCombine(minecraftRoot(), "resources"); | ||||
| } | ||||
| QString LegacyInstance::texturePacksDir() const | ||||
| { | ||||
| 	return FS::PathCombine(minecraftRoot(), "texturepacks"); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::runnableJar() const | ||||
| { | ||||
| 	return FS::PathCombine(binRoot(), "minecraft.jar"); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::modListFile() const | ||||
| { | ||||
| 	return FS::PathCombine(instanceRoot(), "modlist"); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::instanceConfigFolder() const | ||||
| { | ||||
| 	return FS::PathCombine(minecraftRoot(), "config"); | ||||
| } | ||||
|  | ||||
| bool LegacyInstance::shouldRebuild() const | ||||
| { | ||||
| 	return m_settings->get("NeedsRebuild").toBool(); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::currentVersionId() const | ||||
| { | ||||
| 	return m_settings->get("JarVersion").toString(); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::intendedVersionId() const | ||||
| { | ||||
| 	return m_settings->get("IntendedJarVersion").toString(); | ||||
| } | ||||
|  | ||||
| bool LegacyInstance::shouldUpdate() const | ||||
| { | ||||
| 	QVariant var = settings()->get("ShouldUpdate"); | ||||
| 	if (!var.isValid() || var.toBool() == false) | ||||
| 	{ | ||||
| 		return intendedVersionId() != currentVersionId(); | ||||
| 	} | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::defaultBaseJar() const | ||||
| { | ||||
| 	return "versions/" + intendedVersionId() + "/" + intendedVersionId() + ".jar"; | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::defaultCustomBaseJar() const | ||||
| { | ||||
| 	return FS::PathCombine(binRoot(), "mcbackup.jar"); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::typeName() const | ||||
| { | ||||
| 	return tr("Legacy"); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::getStatusbarDescription() | ||||
| { | ||||
| 	return tr("Instance from previous versions."); | ||||
| } | ||||
|  | ||||
| QStringList LegacyInstance::verboseDescription(AuthSessionPtr session) | ||||
| { | ||||
| 	QStringList out; | ||||
|  | ||||
| 	auto alltraits = traits(); | ||||
| 	if(alltraits.size()) | ||||
| 	{ | ||||
| 		out << "Traits:"; | ||||
| 		for (auto trait : alltraits) | ||||
| 		{ | ||||
| 			out << "  " + trait; | ||||
| 		} | ||||
| 		out << ""; | ||||
| 	} | ||||
|  | ||||
| 	QString windowParams; | ||||
| 	if (settings()->get("LaunchMaximized").toBool()) | ||||
| 	{ | ||||
| 		out << "Window size: max (if available)"; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		auto width = settings()->get("MinecraftWinWidth").toInt(); | ||||
| 		auto height = settings()->get("MinecraftWinHeight").toInt(); | ||||
| 		out << "Window size: " + QString::number(width) + " x " + QString::number(height); | ||||
| 	} | ||||
| 	out << ""; | ||||
| 	return out; | ||||
| } | ||||
							
								
								
									
										128
									
								
								api/logic/minecraft/legacy/LegacyInstance.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								api/logic/minecraft/legacy/LegacyInstance.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | ||||
| /* 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 "BaseInstance.h" | ||||
| #include "minecraft/Mod.h" | ||||
|  | ||||
| #include "multimc_logic_export.h" | ||||
|  | ||||
| class ModList; | ||||
| class LegacyModList; | ||||
| class Task; | ||||
| /* | ||||
|  * WHY: Legacy instances - from MultiMC 3 and 4 - are here only to provide a way to upgrade them to the current format. | ||||
|  */ | ||||
| class MULTIMC_LOGIC_EXPORT LegacyInstance : public BaseInstance | ||||
| { | ||||
| 	Q_OBJECT | ||||
| public: | ||||
|  | ||||
| 	explicit LegacyInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir); | ||||
|  | ||||
| 	virtual void init() override {}; | ||||
|  | ||||
| 	/// Path to the instance's minecraft.jar | ||||
| 	QString runnableJar() const; | ||||
|  | ||||
| 	//! Path to the instance's modlist file. | ||||
| 	QString modListFile() const; | ||||
|  | ||||
| 	////// Directories ////// | ||||
| 	QString libDir() const; | ||||
| 	QString savesDir() const; | ||||
| 	QString texturePacksDir() const; | ||||
| 	QString jarModsDir() const; | ||||
| 	QString loaderModsDir() const; | ||||
| 	QString coreModsDir() const; | ||||
| 	QString resourceDir() const; | ||||
| 	virtual QString instanceConfigFolder() const override; | ||||
| 	QString minecraftRoot() const; // Path to the instance's minecraft directory. | ||||
| 	QString binRoot() const; // Path to the instance's minecraft bin directory. | ||||
|  | ||||
| 	/// Get the curent base jar of this instance. By default, it's the | ||||
| 	/// versions/$version/$version.jar | ||||
| 	QString baseJar() const; | ||||
|  | ||||
| 	/// the default base jar of this instance | ||||
| 	QString defaultBaseJar() const; | ||||
| 	/// the default custom base jar of this instance | ||||
| 	QString defaultCustomBaseJar() const; | ||||
|  | ||||
| 	/*! | ||||
| 	 * Whether or not custom base jar is used | ||||
| 	 */ | ||||
| 	bool shouldUseCustomBaseJar() const; | ||||
|  | ||||
| 	/*! | ||||
| 	 * The value of the custom base jar | ||||
| 	 */ | ||||
| 	QString customBaseJar() const; | ||||
|  | ||||
| 	std::shared_ptr<LegacyModList> jarModList() const; | ||||
| 	QList<Mod> getJarMods() const; | ||||
|  | ||||
| 	/*! | ||||
| 	 * Whether or not the instance's minecraft.jar needs to be rebuilt. | ||||
| 	 * If this is true, when the instance launches, its jar mods will be | ||||
| 	 * re-added to a fresh minecraft.jar file. | ||||
| 	 */ | ||||
| 	bool shouldRebuild() const; | ||||
|  | ||||
| 	QString currentVersionId() const; | ||||
| 	QString intendedVersionId() const; | ||||
|  | ||||
| 	QSet<QString> traits() override | ||||
| 	{ | ||||
| 		return {"legacy-instance", "texturepacks"}; | ||||
| 	}; | ||||
|  | ||||
| 	virtual bool shouldUpdate() const; | ||||
| 	virtual shared_qobject_ptr<Task> createUpdateTask() override; | ||||
|  | ||||
| 	virtual QString typeName() const override; | ||||
|  | ||||
| 	bool canExport() const override | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
| 	std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) override | ||||
| 	{ | ||||
| 		return nullptr; | ||||
| 	} | ||||
| 	IPathMatcher::Ptr getLogFileMatcher() override | ||||
| 	{ | ||||
| 		return nullptr; | ||||
| 	} | ||||
| 	QString getLogFileRoot() override | ||||
| 	{ | ||||
| 		return minecraftRoot(); | ||||
| 	} | ||||
|  | ||||
| 	QString getStatusbarDescription() override; | ||||
| 	QStringList verboseDescription(AuthSessionPtr session) override; | ||||
|  | ||||
| 	QProcessEnvironment createEnvironment() override | ||||
| 	{ | ||||
| 		return QProcessEnvironment(); | ||||
| 	} | ||||
| 	QMap<QString, QString> getVariables() const override | ||||
| 	{ | ||||
| 		return {}; | ||||
| 	} | ||||
| protected: | ||||
| 	mutable std::shared_ptr<LegacyModList> jar_mod_list; | ||||
| }; | ||||
							
								
								
									
										171
									
								
								api/logic/minecraft/legacy/LegacyModList.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								api/logic/minecraft/legacy/LegacyModList.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,171 @@ | ||||
| /* 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 "LegacyModList.h" | ||||
| #include <FileSystem.h> | ||||
| #include <QString> | ||||
| #include <QDebug> | ||||
|  | ||||
| LegacyModList::LegacyModList(const QString &dir, const QString &list_file) | ||||
| 	: m_dir(dir), m_list_file(list_file) | ||||
| { | ||||
| 	FS::ensureFolderPathExists(m_dir.absolutePath()); | ||||
| 	m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs | | ||||
| 					QDir::NoSymLinks); | ||||
| 	m_dir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware); | ||||
| } | ||||
|  | ||||
| 	struct OrderItem | ||||
| 	{ | ||||
| 		QString id; | ||||
| 		bool enabled = false; | ||||
| 	}; | ||||
| 	typedef QList<OrderItem> OrderList; | ||||
|  | ||||
| static void internalSort(QList<Mod> &what) | ||||
| { | ||||
| 	auto predicate = [](const Mod &left, const Mod &right) | ||||
| 	{ | ||||
| 		if (left.name() == right.name()) | ||||
| 		{ | ||||
| 			return left.mmc_id().localeAwareCompare(right.mmc_id()) < 0; | ||||
| 		} | ||||
| 		return left.name().localeAwareCompare(right.name()) < 0; | ||||
| 	}; | ||||
| 	std::sort(what.begin(), what.end(), predicate); | ||||
| } | ||||
|  | ||||
| static OrderList readListFile(const QString &m_list_file) | ||||
| { | ||||
| 	OrderList itemList; | ||||
| 	if (m_list_file.isNull() || m_list_file.isEmpty()) | ||||
| 		return itemList; | ||||
|  | ||||
| 	QFile textFile(m_list_file); | ||||
| 	if (!textFile.open(QIODevice::ReadOnly | QIODevice::Text)) | ||||
| 		return OrderList(); | ||||
|  | ||||
| 	QTextStream textStream; | ||||
| 	textStream.setAutoDetectUnicode(true); | ||||
| 	textStream.setDevice(&textFile); | ||||
| 	while (true) | ||||
| 	{ | ||||
| 		QString line = textStream.readLine(); | ||||
| 		if (line.isNull() || line.isEmpty()) | ||||
| 			break; | ||||
| 		else | ||||
| 		{ | ||||
| 			OrderItem it; | ||||
| 			it.enabled = !line.endsWith(".disabled"); | ||||
| 			if (!it.enabled) | ||||
| 			{ | ||||
| 				line.chop(9); | ||||
| 			} | ||||
| 			it.id = line; | ||||
| 			itemList.append(it); | ||||
| 		} | ||||
| 	} | ||||
| 	textFile.close(); | ||||
| 	return itemList; | ||||
| } | ||||
|  | ||||
| bool LegacyModList::update() | ||||
| { | ||||
| 	if (!m_dir.exists() || !m_dir.isReadable()) | ||||
| 		return false; | ||||
|  | ||||
| 	QList<Mod> orderedMods; | ||||
| 	QList<Mod> newMods; | ||||
| 	m_dir.refresh(); | ||||
| 	auto folderContents = m_dir.entryInfoList(); | ||||
| 	bool orderOrStateChanged = false; | ||||
|  | ||||
| 	// first, process the ordered items (if any) | ||||
| 	OrderList listOrder = readListFile(m_list_file); | ||||
| 	for (auto item : listOrder) | ||||
| 	{ | ||||
| 		QFileInfo infoEnabled(m_dir.filePath(item.id)); | ||||
| 		QFileInfo infoDisabled(m_dir.filePath(item.id + ".disabled")); | ||||
| 		int idxEnabled = folderContents.indexOf(infoEnabled); | ||||
| 		int idxDisabled = folderContents.indexOf(infoDisabled); | ||||
| 		bool isEnabled; | ||||
| 		// if both enabled and disabled versions are present, it's a special case... | ||||
| 		if (idxEnabled >= 0 && idxDisabled >= 0) | ||||
| 		{ | ||||
| 			// we only process the one we actually have in the order file. | ||||
| 			// and exactly as we have it. | ||||
| 			// THIS IS A CORNER CASE | ||||
| 			isEnabled = item.enabled; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			// only one is present. | ||||
| 			// we pick the one that we found. | ||||
| 			// we assume the mod was enabled/disabled by external means | ||||
| 			isEnabled = idxEnabled >= 0; | ||||
| 		} | ||||
| 		int idx = isEnabled ? idxEnabled : idxDisabled; | ||||
| 		QFileInfo &info = isEnabled ? infoEnabled : infoDisabled; | ||||
| 		// if the file from the index file exists | ||||
| 		if (idx != -1) | ||||
| 		{ | ||||
| 			// remove from the actual folder contents list | ||||
| 			folderContents.takeAt(idx); | ||||
| 			// append the new mod | ||||
| 			orderedMods.append(Mod(info)); | ||||
| 			if (isEnabled != item.enabled) | ||||
| 				orderOrStateChanged = true; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			orderOrStateChanged = true; | ||||
| 		} | ||||
| 	} | ||||
| 	// if there are any untracked files... | ||||
| 	if (folderContents.size()) | ||||
| 	{ | ||||
| 		// the order surely changed! | ||||
| 		for (auto entry : folderContents) | ||||
| 		{ | ||||
| 			newMods.append(Mod(entry)); | ||||
| 		} | ||||
| 		internalSort(newMods); | ||||
| 		orderedMods.append(newMods); | ||||
| 		orderOrStateChanged = true; | ||||
| 	} | ||||
| 	// otherwise, if we were already tracking some mods | ||||
| 	else if (mods.size()) | ||||
| 	{ | ||||
| 		// if the number doesn't match, order changed. | ||||
| 		if (mods.size() != orderedMods.size()) | ||||
| 			orderOrStateChanged = true; | ||||
| 		// if it does match, compare the mods themselves | ||||
| 		else | ||||
| 			for (int i = 0; i < mods.size(); i++) | ||||
| 			{ | ||||
| 				if (!mods[i].strongCompare(orderedMods[i])) | ||||
| 				{ | ||||
| 					orderOrStateChanged = true; | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 	} | ||||
| 	mods.swap(orderedMods); | ||||
| 	if (orderOrStateChanged && !m_list_file.isEmpty()) | ||||
| 	{ | ||||
| 		qDebug() << "Mod list " << m_list_file << " changed!"; | ||||
| 	} | ||||
| 	return true; | ||||
| } | ||||
							
								
								
									
										56
									
								
								api/logic/minecraft/legacy/LegacyModList.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								api/logic/minecraft/legacy/LegacyModList.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| /* 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 <QList> | ||||
| #include <QString> | ||||
| #include <QDir> | ||||
|  | ||||
| #include "minecraft/Mod.h" | ||||
|  | ||||
| #include "multimc_logic_export.h" | ||||
|  | ||||
| class LegacyInstance; | ||||
| class BaseInstance; | ||||
|  | ||||
| /** | ||||
|  * A legacy mod list. | ||||
|  * Backed by a folder. | ||||
|  */ | ||||
| class MULTIMC_LOGIC_EXPORT LegacyModList | ||||
| { | ||||
| public: | ||||
|  | ||||
| 	LegacyModList(const QString &dir, const QString &list_file = QString()); | ||||
|  | ||||
| 	/// Reloads the mod list and returns true if the list changed. | ||||
| 	bool update(); | ||||
|  | ||||
| 	QDir dir() | ||||
| 	{ | ||||
| 		return m_dir; | ||||
| 	} | ||||
|  | ||||
| 	const QList<Mod> & allMods() | ||||
| 	{ | ||||
| 		return mods; | ||||
| 	} | ||||
|  | ||||
| protected: | ||||
| 	QDir m_dir; | ||||
| 	QString m_list_file; | ||||
| 	QList<Mod> mods; | ||||
| }; | ||||
| @@ -131,6 +131,8 @@ SET(MULTIMC_SOURCES | ||||
| 	pages/ScreenshotsPage.h | ||||
| 	pages/OtherLogsPage.cpp | ||||
| 	pages/OtherLogsPage.h | ||||
| 	pages/LegacyUpgradePage.cpp | ||||
| 	pages/LegacyUpgradePage.h | ||||
| 	pages/WorldListPage.cpp | ||||
| 	pages/WorldListPage.h | ||||
|  | ||||
| @@ -229,7 +231,7 @@ SET(MULTIMC_SOURCES | ||||
|  | ||||
| ######## UIs ######## | ||||
| SET(MULTIMC_UIS | ||||
| 	# Option pages | ||||
| 	# Instance pages | ||||
| 	pages/VersionPage.ui | ||||
| 	pages/ModFolderPage.ui | ||||
| 	pages/LogPage.ui | ||||
| @@ -237,6 +239,7 @@ SET(MULTIMC_UIS | ||||
| 	pages/NotesPage.ui | ||||
| 	pages/ScreenshotsPage.ui | ||||
| 	pages/OtherLogsPage.ui | ||||
| 	pages/LegacyUpgradePage.ui | ||||
| 	pages/WorldListPage.ui | ||||
|  | ||||
| 	# Global settings pages | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| #pragma once | ||||
| #include "minecraft/MinecraftInstance.h" | ||||
| #include "minecraft/legacy/LegacyInstance.h" | ||||
| #include <FileSystem.h> | ||||
| #include "pages/BasePage.h" | ||||
| #include "pages/LogPage.h" | ||||
| @@ -12,6 +13,7 @@ | ||||
| #include "pages/InstanceSettingsPage.h" | ||||
| #include "pages/OtherLogsPage.h" | ||||
| #include "pages/BasePageProvider.h" | ||||
| #include "pages/LegacyUpgradePage.h" | ||||
| #include "pages/WorldListPage.h" | ||||
|  | ||||
|  | ||||
| @@ -44,6 +46,11 @@ public: | ||||
| 			values.append(new ScreenshotsPage(FS::PathCombine(onesix->minecraftRoot(), "screenshots"))); | ||||
| 			values.append(new InstanceSettingsPage(onesix.get())); | ||||
| 		} | ||||
| 		std::shared_ptr<LegacyInstance> legacy = std::dynamic_pointer_cast<LegacyInstance>(inst); | ||||
| 		if(legacy) | ||||
| 		{ | ||||
| 			values.append(new LegacyUpgradePage(legacy.get())); | ||||
| 		} | ||||
| 		auto logMatcher = inst->getLogFileMatcher(); | ||||
| 		if(logMatcher) | ||||
| 		{ | ||||
|   | ||||
							
								
								
									
										25
									
								
								application/pages/LegacyUpgradePage.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								application/pages/LegacyUpgradePage.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| #include "LegacyUpgradePage.h" | ||||
| #include "ui_LegacyUpgradePage.h" | ||||
|  | ||||
| #include "minecraft/legacy/LegacyInstance.h" | ||||
|  | ||||
| LegacyUpgradePage::LegacyUpgradePage(LegacyInstance *inst, QWidget *parent) | ||||
| 	: QWidget(parent), ui(new Ui::LegacyUpgradePage), m_inst(inst) | ||||
| { | ||||
| 	ui->setupUi(this); | ||||
| } | ||||
|  | ||||
| LegacyUpgradePage::~LegacyUpgradePage() | ||||
| { | ||||
| 	delete ui; | ||||
| } | ||||
|  | ||||
| void LegacyUpgradePage::on_upgradeButton_clicked() | ||||
| { | ||||
| 	// now what? | ||||
| } | ||||
|  | ||||
| bool LegacyUpgradePage::shouldDisplay() const | ||||
| { | ||||
| 	return !m_inst->isRunning(); | ||||
| } | ||||
							
								
								
									
										60
									
								
								application/pages/LegacyUpgradePage.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								application/pages/LegacyUpgradePage.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| /* 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 <QWidget> | ||||
|  | ||||
| #include "minecraft/legacy/LegacyInstance.h" | ||||
| #include "pages/BasePage.h" | ||||
| #include <MultiMC.h> | ||||
|  | ||||
| namespace Ui | ||||
| { | ||||
| class LegacyUpgradePage; | ||||
| } | ||||
|  | ||||
| class LegacyUpgradePage : public QWidget, public BasePage | ||||
| { | ||||
| 	Q_OBJECT | ||||
|  | ||||
| public: | ||||
| 	explicit LegacyUpgradePage(LegacyInstance *inst, QWidget *parent = 0); | ||||
| 	virtual ~LegacyUpgradePage(); | ||||
| 	virtual QString displayName() const override | ||||
| 	{ | ||||
| 		return tr("Upgrade"); | ||||
| 	} | ||||
| 	virtual QIcon icon() const override | ||||
| 	{ | ||||
| 		return MMC->getThemedIcon("checkupdate"); | ||||
| 	} | ||||
| 	virtual QString id() const override | ||||
| 	{ | ||||
| 		return "upgrade"; | ||||
| 	} | ||||
| 	virtual QString helpPage() const override | ||||
| 	{ | ||||
| 		return "Legacy-upgrade"; | ||||
| 	} | ||||
| 	virtual bool shouldDisplay() const override; | ||||
| private | ||||
| slots: | ||||
| 	void on_upgradeButton_clicked(); | ||||
|  | ||||
| private: | ||||
| 	Ui::LegacyUpgradePage *ui; | ||||
| 	LegacyInstance *m_inst; | ||||
| }; | ||||
							
								
								
									
										47
									
								
								application/pages/LegacyUpgradePage.ui
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								application/pages/LegacyUpgradePage.ui
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <ui version="4.0"> | ||||
|  <class>LegacyUpgradePage</class> | ||||
|  <widget class="QWidget" name="LegacyUpgradePage"> | ||||
|   <property name="geometry"> | ||||
|    <rect> | ||||
|     <x>0</x> | ||||
|     <y>0</y> | ||||
|     <width>546</width> | ||||
|     <height>405</height> | ||||
|    </rect> | ||||
|   </property> | ||||
|   <layout class="QVBoxLayout" name="verticalLayout_5"> | ||||
|    <property name="leftMargin"> | ||||
|     <number>0</number> | ||||
|    </property> | ||||
|    <property name="topMargin"> | ||||
|     <number>0</number> | ||||
|    </property> | ||||
|    <property name="rightMargin"> | ||||
|     <number>0</number> | ||||
|    </property> | ||||
|    <property name="bottomMargin"> | ||||
|     <number>0</number> | ||||
|    </property> | ||||
|    <item> | ||||
|     <widget class="QTextBrowser" name="textBrowser"> | ||||
|      <property name="html"> | ||||
|       <string><html><body><h1>Upgrade is required</h1><p>MultiMC now supports old Minecraft versions and all the required features in the new (OneSix) instance format. As a consequence, the old (Legacy) format has been entirely disabled and old instances need to be upgraded.</p><p>The upgrade will create a new instance with the same contents as the current one, in the new format. The original instance will remain untouched, in case anything goes wrong in the process.</p><p>Please report any issues on our <a href="https://github.com/MultiMC/MultiMC5/issues">github issues page</a>.</p></body></html></string> | ||||
|      </property> | ||||
|      <property name="openExternalLinks"> | ||||
|       <bool>true</bool> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item> | ||||
|     <widget class="QCommandLinkButton" name="upgradeButton"> | ||||
|      <property name="text"> | ||||
|       <string>Upgrade the instance</string> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|   </layout> | ||||
|  </widget> | ||||
|  <resources/> | ||||
|  <connections/> | ||||
| </ui> | ||||
		Reference in New Issue
	
	Block a user