Implement adding jar mods, break saving library order.
This commit is contained in:
		| @@ -473,6 +473,8 @@ SET(MULTIMC_SOURCES | ||||
| 	logic/OneSixInstance_p.h | ||||
|  | ||||
| 	# OneSix version json infrastructure | ||||
| 	logic/minecraft/InstanceVersion.cpp | ||||
| 	logic/minecraft/InstanceVersion.h | ||||
| 	logic/minecraft/JarMod.cpp | ||||
| 	logic/minecraft/JarMod.h | ||||
| 	logic/minecraft/MinecraftVersion.cpp | ||||
| @@ -494,8 +496,6 @@ SET(MULTIMC_SOURCES | ||||
| 	logic/minecraft/VersionBuildError.h | ||||
| 	logic/minecraft/VersionFile.cpp | ||||
| 	logic/minecraft/VersionFile.h | ||||
| 	logic/minecraft/VersionFinal.cpp | ||||
| 	logic/minecraft/VersionFinal.h | ||||
| 	logic/minecraft/VersionPatch.h | ||||
| 	logic/minecraft/VersionSource.h | ||||
|  | ||||
| @@ -819,8 +819,6 @@ include(CPack) | ||||
|  | ||||
| include(Coverity) | ||||
|  | ||||
| include_directories(${PROJECT_BINARY_DIR}/include) | ||||
|  | ||||
| # Translations | ||||
| add_subdirectory(translations) | ||||
|  | ||||
|   | ||||
| @@ -35,7 +35,7 @@ | ||||
| #include "InstanceSettings.h" | ||||
|  | ||||
| #include "logic/ModList.h" | ||||
| #include "logic/minecraft/VersionFinal.h" | ||||
| #include "logic/minecraft/InstanceVersion.h" | ||||
| #include "logic/EnabledItemFilter.h" | ||||
| #include "logic/forge/ForgeVersionList.h" | ||||
| #include "logic/forge/ForgeInstaller.h" | ||||
| @@ -175,21 +175,34 @@ void InstanceEditDialog::on_removeLibraryBtn_clicked() | ||||
| void InstanceEditDialog::on_jarmodBtn_clicked() | ||||
| { | ||||
| 	QFileDialog w; | ||||
| 	w.setFileMode(QFileDialog::AnyFile); | ||||
| 	// w.setOption(QFileDialog::DontUseNativeDialog, true); | ||||
| 	QListView *l = w.findChild<QListView *>("listView"); | ||||
| 	if (l) | ||||
| 	QSet<QString> locations; | ||||
| 	QString modsFolder = MMC->settings()->get("CentralModsDir").toString(); | ||||
| 	auto f = [&](QStandardPaths::StandardLocation l) | ||||
| 	{ | ||||
| 		l->setSelectionMode(QAbstractItemView::ExtendedSelection); | ||||
| 	} | ||||
| 	QTreeView *t = w.findChild<QTreeView *>(); | ||||
| 	if (t) | ||||
| 		QString location = QStandardPaths::writableLocation(l); | ||||
| 		if(!QFileInfo::exists(location)) | ||||
| 			return; | ||||
| 		locations.insert(location); | ||||
| 	}; | ||||
| 	f(QStandardPaths::DesktopLocation); | ||||
| 	f(QStandardPaths::DocumentsLocation); | ||||
| 	f(QStandardPaths::DownloadLocation); | ||||
| 	f(QStandardPaths::HomeLocation); | ||||
| 	QList<QUrl> urls; | ||||
| 	for(auto location: locations) | ||||
| 	{ | ||||
| 		t->setSelectionMode(QAbstractItemView::ExtendedSelection); | ||||
| 		urls.append(QUrl::fromLocalFile(location)); | ||||
| 	} | ||||
| 	int result = w.exec(); | ||||
| 	auto list = w.selectedFiles(); | ||||
| 	QLOG_INFO() << list.join(" "); | ||||
| 	urls.append(QUrl::fromLocalFile(modsFolder)); | ||||
|  | ||||
| 	w.setFileMode(QFileDialog::ExistingFiles); | ||||
| 	w.setAcceptMode(QFileDialog::AcceptOpen); | ||||
| 	w.setNameFilter(tr("Minecraft jar mods (*.zip *.jar)")); | ||||
| 	w.setDirectory(modsFolder); | ||||
| 	w.setSidebarUrls(urls); | ||||
|  | ||||
| 	if(w.exec()); | ||||
| 		m_version->installJarMods(w.selectedFiles()); | ||||
| } | ||||
|  | ||||
| void InstanceEditDialog::on_resetLibraryOrderBtn_clicked() | ||||
| @@ -214,7 +227,7 @@ void InstanceEditDialog::on_moveLibraryUpBtn_clicked() | ||||
| 	{ | ||||
| 		const int row = ui->libraryTreeView->selectionModel()->selectedRows().first().row(); | ||||
| 		const int newRow = 0; | ||||
| 		m_version->move(row, VersionFinal::MoveUp); | ||||
| 		m_version->move(row, InstanceVersion::MoveUp); | ||||
| 		// ui->libraryTreeView->selectionModel()->setCurrentIndex(m_version->index(newRow), | ||||
| 		// QItemSelectionModel::ClearAndSelect); | ||||
| 	} | ||||
| @@ -234,7 +247,7 @@ void InstanceEditDialog::on_moveLibraryDownBtn_clicked() | ||||
| 	{ | ||||
| 		const int row = ui->libraryTreeView->selectionModel()->selectedRows().first().row(); | ||||
| 		const int newRow = 0; | ||||
| 		m_version->move(row, VersionFinal::MoveDown); | ||||
| 		m_version->move(row, InstanceVersion::MoveDown); | ||||
| 		// ui->libraryTreeView->selectionModel()->setCurrentIndex(m_version->index(newRow), | ||||
| 		// QItemSelectionModel::ClearAndSelect); | ||||
| 	} | ||||
|   | ||||
| @@ -80,7 +80,7 @@ protected: | ||||
|  | ||||
| private: | ||||
| 	Ui::InstanceEditDialog *ui; | ||||
| 	std::shared_ptr<VersionFinal> m_version; | ||||
| 	std::shared_ptr<InstanceVersion> m_version; | ||||
| 	std::shared_ptr<ModList> m_mods; | ||||
| 	std::shared_ptr<ModList> m_coremods; | ||||
| 	std::shared_ptr<ModList> m_jarmods; | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| #include "OneSixFTBInstance.h" | ||||
|  | ||||
| #include "logic/minecraft/VersionFinal.h" | ||||
| #include "logic/minecraft/InstanceVersion.h" | ||||
| #include "logic/minecraft/OneSixLibrary.h" | ||||
| #include "logic/minecraft/VersionBuilder.h" | ||||
| #include "tasks/SequentialTask.h" | ||||
|   | ||||
| @@ -23,7 +23,7 @@ | ||||
|  | ||||
| #include "logic/OneSixInstance_p.h" | ||||
| #include "logic/OneSixUpdate.h" | ||||
| #include "logic/minecraft/VersionFinal.h" | ||||
| #include "logic/minecraft/InstanceVersion.h" | ||||
| #include "minecraft/VersionBuildError.h" | ||||
|  | ||||
| #include "logic/assets/AssetsUtils.h" | ||||
| @@ -37,8 +37,7 @@ OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *settings, | ||||
| { | ||||
| 	I_D(OneSixInstance); | ||||
| 	d->m_settings->registerSetting("IntendedVersion", ""); | ||||
| 	d->m_settings->registerSetting("ShouldUpdate", false); | ||||
| 	d->version.reset(new VersionFinal(this, this)); | ||||
| 	d->version.reset(new InstanceVersion(this, this)); | ||||
| } | ||||
|  | ||||
| void OneSixInstance::init() | ||||
| @@ -82,7 +81,7 @@ QString replaceTokensIn(QString text, QMap<QString, QString> with) | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| QDir OneSixInstance::reconstructAssets(std::shared_ptr<VersionFinal> version) | ||||
| QDir OneSixInstance::reconstructAssets(std::shared_ptr<InstanceVersion> version) | ||||
| { | ||||
| 	QDir assetsDir = QDir("assets/"); | ||||
| 	QDir indexDir = QDir(PathCombine(assetsDir.path(), "indexes")); | ||||
| @@ -183,7 +182,7 @@ QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session) | ||||
| 	return parts; | ||||
| } | ||||
|  | ||||
| bool OneSixInstance::prepareForLaunch(AuthSessionPtr account, QString &launchScript) | ||||
| bool OneSixInstance::prepareForLaunch(AuthSessionPtr session, QString &launchScript) | ||||
| { | ||||
| 	I_D(OneSixInstance); | ||||
|  | ||||
| @@ -227,7 +226,7 @@ bool OneSixInstance::prepareForLaunch(AuthSessionPtr account, QString &launchScr | ||||
| 	} | ||||
|  | ||||
| 	// generic minecraft params | ||||
| 	for (auto param : processMinecraftArgs(account)) | ||||
| 	for (auto param : processMinecraftArgs(session)) | ||||
| 	{ | ||||
| 		launchScript += "param " + param + "\n"; | ||||
| 	} | ||||
| @@ -319,7 +318,6 @@ QDialog *OneSixInstance::createModEditDialog(QWidget *parent) | ||||
| bool OneSixInstance::setIntendedVersionId(QString version) | ||||
| { | ||||
| 	settings().set("IntendedVersion", version); | ||||
| 	setShouldUpdate(true); | ||||
| 	QFile::remove(PathCombine(instanceRoot(), "version.json")); | ||||
| 	clearVersion(); | ||||
| 	return true; | ||||
| @@ -330,18 +328,12 @@ QString OneSixInstance::intendedVersionId() const | ||||
| 	return settings().get("IntendedVersion").toString(); | ||||
| } | ||||
|  | ||||
| void OneSixInstance::setShouldUpdate(bool val) | ||||
| void OneSixInstance::setShouldUpdate(bool) | ||||
| { | ||||
| 	settings().set("ShouldUpdate", val); | ||||
| } | ||||
|  | ||||
| bool OneSixInstance::shouldUpdate() const | ||||
| { | ||||
| 	QVariant var = settings().get("ShouldUpdate"); | ||||
| 	if (!var.isValid() || var.toBool() == false) | ||||
| 	{ | ||||
| 		return intendedVersionId() != currentVersionId(); | ||||
| 	} | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| @@ -403,7 +395,7 @@ void OneSixInstance::clearVersion() | ||||
| 	emit versionReloaded(); | ||||
| } | ||||
|  | ||||
| std::shared_ptr<VersionFinal> OneSixInstance::getFullVersion() const | ||||
| std::shared_ptr<InstanceVersion> OneSixInstance::getFullVersion() const | ||||
| { | ||||
| 	I_D(const OneSixInstance); | ||||
| 	return d->version; | ||||
|   | ||||
| @@ -17,7 +17,7 @@ | ||||
|  | ||||
| #include "BaseInstance.h" | ||||
|  | ||||
| #include "logic/minecraft/VersionFinal.h" | ||||
| #include "logic/minecraft/InstanceVersion.h" | ||||
| #include "logic/ModList.h" | ||||
|  | ||||
| class OneSixInstance : public BaseInstance | ||||
| @@ -69,7 +69,7 @@ public: | ||||
| 	void clearVersion(); | ||||
| 	 | ||||
| 	/// get the current full version info | ||||
| 	std::shared_ptr<VersionFinal> getFullVersion() const; | ||||
| 	std::shared_ptr<InstanceVersion> getFullVersion() const; | ||||
| 	 | ||||
| 	/// is the current version original, or custom? | ||||
| 	virtual bool versionIsCustom() override; | ||||
| @@ -97,5 +97,5 @@ signals: | ||||
|  | ||||
| private: | ||||
| 	QStringList processMinecraftArgs(AuthSessionPtr account); | ||||
| 	QDir reconstructAssets(std::shared_ptr<VersionFinal> version); | ||||
| 	QDir reconstructAssets(std::shared_ptr<InstanceVersion> version); | ||||
| }; | ||||
|   | ||||
| @@ -18,13 +18,13 @@ | ||||
| #include "logic/BaseInstance_p.h" | ||||
|  | ||||
| class ModList; | ||||
| class VersionFinal; | ||||
| class InstanceVersion; | ||||
|  | ||||
| class OneSixInstancePrivate : public BaseInstancePrivate | ||||
| { | ||||
| public: | ||||
| 	virtual ~OneSixInstancePrivate() {}; | ||||
| 	std::shared_ptr<VersionFinal> version; | ||||
| 	std::shared_ptr<InstanceVersion> version; | ||||
| 	std::shared_ptr<ModList> jar_mod_list; | ||||
| 	std::shared_ptr<ModList> loader_mod_list; | ||||
| 	std::shared_ptr<ModList> core_mod_list; | ||||
|   | ||||
| @@ -27,7 +27,7 @@ | ||||
|  | ||||
| #include "logic/BaseInstance.h" | ||||
| #include "logic/minecraft/MinecraftVersionList.h" | ||||
| #include "logic/minecraft/VersionFinal.h" | ||||
| #include "logic/minecraft/InstanceVersion.h" | ||||
| #include "logic/minecraft/OneSixLibrary.h" | ||||
| #include "logic/OneSixInstance.h" | ||||
| #include "logic/forge/ForgeMirrors.h" | ||||
| @@ -85,7 +85,7 @@ void OneSixUpdate::assetIndexStart() | ||||
| { | ||||
| 	setStatus(tr("Updating assets index...")); | ||||
| 	OneSixInstance *inst = (OneSixInstance *)m_inst; | ||||
| 	std::shared_ptr<VersionFinal> version = inst->getFullVersion(); | ||||
| 	std::shared_ptr<InstanceVersion> version = inst->getFullVersion(); | ||||
| 	QString assetName = version->assets; | ||||
| 	QUrl indexUrl = "http://" + URLConstants::AWS_DOWNLOAD_INDEXES + assetName + ".json"; | ||||
| 	QString localPath = assetName + ".json"; | ||||
| @@ -109,7 +109,7 @@ void OneSixUpdate::assetIndexFinished() | ||||
| 	AssetsIndex index; | ||||
|  | ||||
| 	OneSixInstance *inst = (OneSixInstance *)m_inst; | ||||
| 	std::shared_ptr<VersionFinal> version = inst->getFullVersion(); | ||||
| 	std::shared_ptr<InstanceVersion> version = inst->getFullVersion(); | ||||
| 	QString assetName = version->assets; | ||||
|  | ||||
| 	QString asset_fname = "assets/indexes/" + assetName + ".json"; | ||||
| @@ -185,7 +185,7 @@ void OneSixUpdate::jarlibStart() | ||||
| 	} | ||||
|  | ||||
| 	// Build a list of URLs that will need to be downloaded. | ||||
| 	std::shared_ptr<VersionFinal> version = inst->getFullVersion(); | ||||
| 	std::shared_ptr<InstanceVersion> version = inst->getFullVersion(); | ||||
| 	// minecraft.jar for this version | ||||
| 	{ | ||||
| 		QString version_id = version->id; | ||||
| @@ -283,7 +283,7 @@ void OneSixUpdate::jarlibStart() | ||||
| void OneSixUpdate::jarlibFinished() | ||||
| { | ||||
| 	OneSixInstance *inst = (OneSixInstance *)m_inst; | ||||
| 	std::shared_ptr<VersionFinal> version = inst->getFullVersion(); | ||||
| 	std::shared_ptr<InstanceVersion> version = inst->getFullVersion(); | ||||
|  | ||||
| 	// create stripped jar, if needed | ||||
| 	if (version->hasJarMods()) | ||||
| @@ -407,7 +407,7 @@ void OneSixUpdate::fmllibsStart() | ||||
| { | ||||
| 	// Get the mod list | ||||
| 	OneSixInstance *inst = (OneSixInstance *)m_inst; | ||||
| 	std::shared_ptr<VersionFinal> fullversion = inst->getFullVersion(); | ||||
| 	std::shared_ptr<InstanceVersion> fullversion = inst->getFullVersion(); | ||||
| 	bool forge_present = false; | ||||
|  | ||||
| 	QString version = inst->intendedVersionId(); | ||||
|   | ||||
| @@ -14,7 +14,7 @@ | ||||
|  */ | ||||
|  | ||||
| #include "ForgeInstaller.h" | ||||
| #include "logic/minecraft/VersionFinal.h" | ||||
| #include "logic/minecraft/InstanceVersion.h" | ||||
| #include "logic/minecraft/OneSixLibrary.h" | ||||
| #include "logic/net/HttpMetaCache.h" | ||||
| #include "logic/tasks/Task.h" | ||||
| @@ -40,7 +40,7 @@ ForgeInstaller::ForgeInstaller() : BaseInstaller() | ||||
| } | ||||
| void ForgeInstaller::prepare(const QString &filename, const QString &universalUrl) | ||||
| { | ||||
| 	std::shared_ptr<VersionFinal> newVersion; | ||||
| 	std::shared_ptr<InstanceVersion> newVersion; | ||||
| 	m_universal_url = universalUrl; | ||||
|  | ||||
| 	QuaZip zip(filename); | ||||
| @@ -73,7 +73,7 @@ void ForgeInstaller::prepare(const QString &filename, const QString &universalUr | ||||
|  | ||||
| 	// read the forge version info | ||||
| 	{ | ||||
| 		newVersion = VersionFinal::fromJson(versionInfoVal.toObject()); | ||||
| 		newVersion = InstanceVersion::fromJson(versionInfoVal.toObject()); | ||||
| 		if (!newVersion) | ||||
| 			return; | ||||
| 	} | ||||
|   | ||||
| @@ -20,7 +20,7 @@ | ||||
| #include <QString> | ||||
| #include <memory> | ||||
|  | ||||
| class VersionFinal; | ||||
| class InstanceVersion; | ||||
| class ForgeInstallTask; | ||||
| class ForgeVersion; | ||||
|  | ||||
| @@ -40,7 +40,7 @@ protected: | ||||
|  | ||||
| private: | ||||
| 	// the parsed version json, read from the installer | ||||
| 	std::shared_ptr<VersionFinal> m_forge_json; | ||||
| 	std::shared_ptr<InstanceVersion> m_forge_json; | ||||
| 	// the actual forge version | ||||
| 	std::shared_ptr<ForgeVersion> m_forge_version; | ||||
| 	QString internalPath; | ||||
|   | ||||
| @@ -20,7 +20,7 @@ | ||||
|  | ||||
| #include "logger/QsLog.h" | ||||
|  | ||||
| #include "logic/minecraft/VersionFinal.h" | ||||
| #include "logic/minecraft/InstanceVersion.h" | ||||
| #include "logic/minecraft/OneSixLibrary.h" | ||||
| #include "logic/OneSixInstance.h" | ||||
| #include "MultiMC.h" | ||||
|   | ||||
| @@ -16,19 +16,22 @@ | ||||
| #include <QDebug> | ||||
| #include <QFile> | ||||
| #include <QDir> | ||||
| #include <QUuid> | ||||
| #include <QJsonDocument> | ||||
| #include <QJsonArray> | ||||
| #include <pathutils.h> | ||||
| 
 | ||||
| #include "logic/minecraft/VersionFinal.h" | ||||
| #include "logic/minecraft/InstanceVersion.h" | ||||
| #include "logic/minecraft/VersionBuilder.h" | ||||
| #include "logic/OneSixInstance.h" | ||||
| 
 | ||||
| VersionFinal::VersionFinal(OneSixInstance *instance, QObject *parent) | ||||
| InstanceVersion::InstanceVersion(OneSixInstance *instance, QObject *parent) | ||||
| 	: QAbstractListModel(parent), m_instance(instance) | ||||
| { | ||||
| 	clear(); | ||||
| } | ||||
| 
 | ||||
| void VersionFinal::reload(const QStringList &external) | ||||
| void InstanceVersion::reload(const QStringList &external) | ||||
| { | ||||
| 	beginResetModel(); | ||||
| 	VersionBuilder::build(this, m_instance, external); | ||||
| @@ -36,7 +39,7 @@ void VersionFinal::reload(const QStringList &external) | ||||
| 	endResetModel(); | ||||
| } | ||||
| 
 | ||||
| void VersionFinal::clear() | ||||
| void InstanceVersion::clear() | ||||
| { | ||||
| 	id.clear(); | ||||
| 	m_updateTimeString.clear(); | ||||
| @@ -56,12 +59,12 @@ void VersionFinal::clear() | ||||
| 	traits.clear(); | ||||
| } | ||||
| 
 | ||||
| bool VersionFinal::canRemove(const int index) const | ||||
| bool InstanceVersion::canRemove(const int index) const | ||||
| { | ||||
| 	return VersionPatches.at(index)->isMoveable(); | ||||
| } | ||||
| 
 | ||||
| bool VersionFinal::preremove(VersionPatchPtr patch) | ||||
| bool InstanceVersion::preremove(VersionPatchPtr patch) | ||||
| { | ||||
| 	bool ok = true; | ||||
| 	for(auto & jarmod: patch->getJarMods()) | ||||
| @@ -74,7 +77,7 @@ bool VersionFinal::preremove(VersionPatchPtr patch) | ||||
| 	return ok; | ||||
| } | ||||
| 
 | ||||
| bool VersionFinal::remove(const int index) | ||||
| bool InstanceVersion::remove(const int index) | ||||
| { | ||||
| 	if (!canRemove(index)) | ||||
| 		return false; | ||||
| @@ -91,7 +94,7 @@ bool VersionFinal::remove(const int index) | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| bool VersionFinal::remove(const QString id) | ||||
| bool InstanceVersion::remove(const QString id) | ||||
| { | ||||
| 	int i = 0; | ||||
| 	for (auto patch : VersionPatches) | ||||
| @@ -105,7 +108,7 @@ bool VersionFinal::remove(const QString id) | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| QString VersionFinal::versionFileId(const int index) const | ||||
| QString InstanceVersion::versionFileId(const int index) const | ||||
| { | ||||
| 	if (index < 0 || index >= VersionPatches.size()) | ||||
| 	{ | ||||
| @@ -114,7 +117,7 @@ QString VersionFinal::versionFileId(const int index) const | ||||
| 	return VersionPatches.at(index)->getPatchID(); | ||||
| } | ||||
| 
 | ||||
| VersionPatchPtr VersionFinal::versionPatch(const QString &id) | ||||
| VersionPatchPtr InstanceVersion::versionPatch(const QString &id) | ||||
| { | ||||
| 	for (auto file : VersionPatches) | ||||
| 	{ | ||||
| @@ -126,7 +129,7 @@ VersionPatchPtr VersionFinal::versionPatch(const QString &id) | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| VersionPatchPtr VersionFinal::versionPatch(int index) | ||||
| VersionPatchPtr InstanceVersion::versionPatch(int index) | ||||
| { | ||||
| 	if(index < 0 || index >= VersionPatches.size()) | ||||
| 		return 0; | ||||
| @@ -134,22 +137,22 @@ VersionPatchPtr VersionFinal::versionPatch(int index) | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| bool VersionFinal::hasJarMods() | ||||
| bool InstanceVersion::hasJarMods() | ||||
| { | ||||
| 	return !jarMods.isEmpty(); | ||||
| } | ||||
| 
 | ||||
| bool VersionFinal::hasFtbPack() | ||||
| bool InstanceVersion::hasFtbPack() | ||||
| { | ||||
| 	return versionPatch("org.multimc.ftb.pack.json") != nullptr; | ||||
| } | ||||
| 
 | ||||
| bool VersionFinal::removeFtbPack() | ||||
| bool InstanceVersion::removeFtbPack() | ||||
| { | ||||
| 	return remove("org.multimc.ftb.pack.json"); | ||||
| } | ||||
| 
 | ||||
| bool VersionFinal::isVanilla() | ||||
| bool InstanceVersion::isVanilla() | ||||
| { | ||||
| 	QDir patches(PathCombine(m_instance->instanceRoot(), "patches/")); | ||||
| 	if(VersionPatches.size() > 1) | ||||
| @@ -159,7 +162,7 @@ bool VersionFinal::isVanilla() | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| bool VersionFinal::revertToVanilla() | ||||
| bool InstanceVersion::revertToVanilla() | ||||
| { | ||||
| 	beginResetModel(); | ||||
| 	auto it = VersionPatches.begin(); | ||||
| @@ -187,12 +190,12 @@ bool VersionFinal::revertToVanilla() | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| bool VersionFinal::usesLegacyCustomJson() | ||||
| bool InstanceVersion::usesLegacyCustomJson() | ||||
| { | ||||
| 	return QFile::exists(PathCombine(m_instance->instanceRoot(), "custom.json")); | ||||
| } | ||||
| 
 | ||||
| QList<std::shared_ptr<OneSixLibrary> > VersionFinal::getActiveNormalLibs() | ||||
| QList<std::shared_ptr<OneSixLibrary> > InstanceVersion::getActiveNormalLibs() | ||||
| { | ||||
| 	QList<std::shared_ptr<OneSixLibrary> > output; | ||||
| 	for (auto lib : libraries) | ||||
| @@ -204,7 +207,7 @@ QList<std::shared_ptr<OneSixLibrary> > VersionFinal::getActiveNormalLibs() | ||||
| 	} | ||||
| 	return output; | ||||
| } | ||||
| QList<std::shared_ptr<OneSixLibrary> > VersionFinal::getActiveNativeLibs() | ||||
| QList<std::shared_ptr<OneSixLibrary> > InstanceVersion::getActiveNativeLibs() | ||||
| { | ||||
| 	QList<std::shared_ptr<OneSixLibrary> > output; | ||||
| 	for (auto lib : libraries) | ||||
| @@ -217,9 +220,9 @@ QList<std::shared_ptr<OneSixLibrary> > VersionFinal::getActiveNativeLibs() | ||||
| 	return output; | ||||
| } | ||||
| 
 | ||||
| std::shared_ptr<VersionFinal> VersionFinal::fromJson(const QJsonObject &obj) | ||||
| std::shared_ptr<InstanceVersion> InstanceVersion::fromJson(const QJsonObject &obj) | ||||
| { | ||||
| 	std::shared_ptr<VersionFinal> version(new VersionFinal(0)); | ||||
| 	std::shared_ptr<InstanceVersion> version(new InstanceVersion(0)); | ||||
| 	try | ||||
| 	{ | ||||
| 		VersionBuilder::readJsonAndApplyToVersion(version.get(), obj); | ||||
| @@ -231,7 +234,7 @@ std::shared_ptr<VersionFinal> VersionFinal::fromJson(const QJsonObject &obj) | ||||
| 	return version; | ||||
| } | ||||
| 
 | ||||
| QVariant VersionFinal::data(const QModelIndex &index, int role) const | ||||
| QVariant InstanceVersion::data(const QModelIndex &index, int role) const | ||||
| { | ||||
| 	if (!index.isValid()) | ||||
| 		return QVariant(); | ||||
| @@ -256,7 +259,7 @@ QVariant VersionFinal::data(const QModelIndex &index, int role) const | ||||
| 	} | ||||
| 	return QVariant(); | ||||
| } | ||||
| QVariant VersionFinal::headerData(int section, Qt::Orientation orientation, int role) const | ||||
| QVariant InstanceVersion::headerData(int section, Qt::Orientation orientation, int role) const | ||||
| { | ||||
| 	if (orientation == Qt::Horizontal) | ||||
| 	{ | ||||
| @@ -275,33 +278,27 @@ QVariant VersionFinal::headerData(int section, Qt::Orientation orientation, int | ||||
| 	} | ||||
| 	return QVariant(); | ||||
| } | ||||
| Qt::ItemFlags VersionFinal::flags(const QModelIndex &index) const | ||||
| Qt::ItemFlags InstanceVersion::flags(const QModelIndex &index) const | ||||
| { | ||||
| 	if (!index.isValid()) | ||||
| 		return Qt::NoItemFlags; | ||||
| 	return Qt::ItemIsSelectable | Qt::ItemIsEnabled; | ||||
| } | ||||
| 
 | ||||
| int VersionFinal::rowCount(const QModelIndex &parent) const | ||||
| int InstanceVersion::rowCount(const QModelIndex &parent) const | ||||
| { | ||||
| 	return VersionPatches.size(); | ||||
| } | ||||
| 
 | ||||
| int VersionFinal::columnCount(const QModelIndex &parent) const | ||||
| int InstanceVersion::columnCount(const QModelIndex &parent) const | ||||
| { | ||||
| 	return 2; | ||||
| } | ||||
| 
 | ||||
| QMap<QString, int> VersionFinal::getExistingOrder() const | ||||
| QMap<QString, int> InstanceVersion::getExistingOrder() const | ||||
| { | ||||
| 	QMap<QString, int> order; | ||||
| 	// default
 | ||||
| 	{ | ||||
| 		for (auto file : VersionPatches) | ||||
| 		{ | ||||
| 			order.insert(file->getPatchID(), file->getOrder()); | ||||
| 		} | ||||
| 	} | ||||
| 	int index = 0; | ||||
| 	// overriden
 | ||||
| 	{ | ||||
| 		QMap<QString, int> overridenOrder = VersionBuilder::readOverrideOrders(m_instance); | ||||
| @@ -313,87 +310,71 @@ QMap<QString, int> VersionFinal::getExistingOrder() const | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	for(auto item: VersionPatches) | ||||
| 	{ | ||||
| 		// things with fixed (negative) order.
 | ||||
| 		if(!item->isMoveable()) | ||||
| 			continue; | ||||
| 		// the other things.
 | ||||
| 		auto id = item->getPatchID(); | ||||
| 		order[id] = index; | ||||
| 		index++; | ||||
| 	} | ||||
| 	return order; | ||||
| } | ||||
| 
 | ||||
| void VersionFinal::move(const int index, const MoveDirection direction) | ||||
| void InstanceVersion::move(const int index, const MoveDirection direction) | ||||
| { | ||||
| 	int theirIndex; | ||||
| 	int theirIndex_qt; | ||||
| 	if (direction == MoveUp) | ||||
| 	{ | ||||
| 		theirIndex_qt = theirIndex = index - 1; | ||||
| 		theirIndex = index - 1; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		theirIndex = index + 1; | ||||
| 		theirIndex_qt = index + 2; | ||||
| 	} | ||||
| 	 | ||||
| 	if (index < 0 || index >= VersionPatches.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 || !from->isMoveable() || !from->isMoveable()) | ||||
| 	if (!from || !to || !to->isMoveable() || !from->isMoveable()) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
| 	if(direction == MoveDown) | ||||
| 	{ | ||||
| 		beginMoveRows(QModelIndex(), index, index, QModelIndex(), theirIndex_qt); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		beginMoveRows(QModelIndex(), index, index, QModelIndex(), theirIndex_qt); | ||||
| 	} | ||||
| 
 | ||||
| 	beginMoveRows(QModelIndex(), index, index, QModelIndex(), togap); | ||||
| 	VersionPatches.swap(index, theirIndex); | ||||
| 	endMoveRows(); | ||||
| 
 | ||||
| 	auto order = getExistingOrder(); | ||||
| 	order[from->getPatchID()] = theirIndex; | ||||
| 	order[to->getPatchID()] = index; | ||||
| 
 | ||||
| 	if (!VersionBuilder::writeOverrideOrders(order, m_instance)) | ||||
| 	{ | ||||
| 		throw MMCError(tr("Couldn't save the new order")); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		reapply(); | ||||
| 	} | ||||
| 	reapply(); | ||||
| } | ||||
| void VersionFinal::resetOrder() | ||||
| void InstanceVersion::resetOrder() | ||||
| { | ||||
| 	QDir(m_instance->instanceRoot()).remove("order.json"); | ||||
| 	reapply(); | ||||
| } | ||||
| 
 | ||||
| void VersionFinal::reapply(const bool alreadyReseting) | ||||
| void InstanceVersion::reapply(const bool alreadyReseting) | ||||
| { | ||||
| 	if (!alreadyReseting) | ||||
| 	{ | ||||
| 		beginResetModel(); | ||||
| 	} | ||||
| 
 | ||||
| 	clear(); | ||||
| 
 | ||||
| 	auto existingOrders = getExistingOrder(); | ||||
| 	QList<int> orders = existingOrders.values(); | ||||
| 	std::sort(orders.begin(), orders.end()); | ||||
| 	QList<VersionPatchPtr> newVersionFiles; | ||||
| 	for (auto order : orders) | ||||
| 	for(auto file: VersionPatches) | ||||
| 	{ | ||||
| 		auto file = versionPatch(existingOrders.key(order)); | ||||
| 		newVersionFiles.append(file); | ||||
| 		file->applyTo(this); | ||||
| 	} | ||||
| 	VersionPatches.swap(newVersionFiles); | ||||
| 	finalize(); | ||||
| 	if (!alreadyReseting) | ||||
| 	{ | ||||
| 		endResetModel(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void VersionFinal::finalize() | ||||
| void InstanceVersion::finalize() | ||||
| { | ||||
| 	// HACK: deny april fools. my head hurts enough already.
 | ||||
| 	QDate now = QDate::currentDate(); | ||||
| @@ -430,3 +411,83 @@ void VersionFinal::finalize() | ||||
| 	finalizeArguments(minecraftArguments, processArguments); | ||||
| } | ||||
| 
 | ||||
| void InstanceVersion::installJarMods(QStringList selectedFiles) | ||||
| { | ||||
| 	for(auto filename: selectedFiles) | ||||
| 	{ | ||||
| 		installJarModByFilename(filename); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void InstanceVersion::installJarModByFilename(QString filepath) | ||||
| { | ||||
| 	QString patchDir = PathCombine(m_instance->instanceRoot(), "patches"); | ||||
| 	if(!ensureFolderPathExists(patchDir)) | ||||
| 	{ | ||||
| 		// THROW...
 | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!ensureFolderPathExists(m_instance->jarModsDir())) | ||||
| 	{ | ||||
| 		// THROW...
 | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	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 = PathCombine(m_instance->jarModsDir(), target_filename); | ||||
| 
 | ||||
| 	QFileInfo targetInfo(finalPath); | ||||
| 	if(targetInfo.exists()) | ||||
| 	{ | ||||
| 		// THROW
 | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!QFile::copy(sourceInfo.absoluteFilePath(),QFileInfo(finalPath).absoluteFilePath())) | ||||
| 	{ | ||||
| 		// THROW
 | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	auto f = std::make_shared<VersionFile>(); | ||||
| 	auto jarMod = std::make_shared<Jarmod>(); | ||||
| 	jarMod->name = target_filename; | ||||
| 	f->jarMods.append(jarMod); | ||||
| 	f->name = target_name; | ||||
| 	f->fileId = target_id; | ||||
| 	f->order = getFreeOrderNumber(); | ||||
| 	 | ||||
| 	QFile file(PathCombine(patchDir, target_id + ".json")); | ||||
| 	if (!file.open(QFile::WriteOnly)) | ||||
| 	{ | ||||
| 		QLOG_ERROR() << "Error opening" << file.fileName() | ||||
| 					 << "for reading:" << file.errorString(); | ||||
| 		return; | ||||
| 		// THROW
 | ||||
| 	} | ||||
| 	file.write(f->toJson(true).toJson()); | ||||
| 	file.close(); | ||||
| 	int index = VersionPatches.size(); | ||||
| 	beginInsertRows(QModelIndex(), index, index); | ||||
| 	VersionPatches.append(f); | ||||
| 	endInsertRows(); | ||||
| } | ||||
| 
 | ||||
| int InstanceVersion::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: VersionPatches) | ||||
| 	{ | ||||
| 		int order = thing->getOrder(); | ||||
| 		if(order > largest) | ||||
| 			largest = order; | ||||
| 	} | ||||
| 	return largest + 1; | ||||
| } | ||||
| @@ -27,11 +27,11 @@ | ||||
| 
 | ||||
| class OneSixInstance; | ||||
| 
 | ||||
| class VersionFinal : public QAbstractListModel | ||||
| class InstanceVersion : public QAbstractListModel | ||||
| { | ||||
| 	Q_OBJECT | ||||
| public: | ||||
| 	explicit VersionFinal(OneSixInstance *instance, QObject *parent = 0); | ||||
| 	explicit InstanceVersion(OneSixInstance *instance, QObject *parent = 0); | ||||
| 
 | ||||
| 	virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; | ||||
| 	virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; | ||||
| @@ -58,10 +58,11 @@ public: | ||||
| 	 | ||||
| 	// does this version have any jar mods?
 | ||||
| 	bool hasJarMods(); | ||||
| 	 | ||||
| 	void installJarMods(QStringList selectedFiles); | ||||
| 	void installJarModByFilename(QString filepath); | ||||
| 
 | ||||
| 	// does this version still use a legacy custom.json file?
 | ||||
| 	bool usesLegacyCustomJson(); | ||||
| 	 | ||||
| 
 | ||||
| 	enum MoveDirection { MoveUp, MoveDown }; | ||||
| 	void move(const int index, const MoveDirection direction); | ||||
| @@ -80,7 +81,7 @@ public: | ||||
| 	QList<std::shared_ptr<OneSixLibrary>> getActiveNormalLibs(); | ||||
| 	QList<std::shared_ptr<OneSixLibrary>> getActiveNativeLibs(); | ||||
| 
 | ||||
| 	static std::shared_ptr<VersionFinal> fromJson(const QJsonObject &obj); | ||||
| 	static std::shared_ptr<InstanceVersion> fromJson(const QJsonObject &obj); | ||||
| 
 | ||||
| private: | ||||
| 	bool preremove(VersionPatchPtr patch); | ||||
| @@ -176,4 +177,5 @@ public: | ||||
| private: | ||||
| 	OneSixInstance *m_instance; | ||||
| 	QMap<QString, int> getExistingOrder() const; | ||||
| 	int getFreeOrderNumber(); | ||||
| }; | ||||
| @@ -1,5 +1,5 @@ | ||||
| #include "MinecraftVersion.h" | ||||
| #include "VersionFinal.h" | ||||
| #include "InstanceVersion.h" | ||||
| #include "VersionBuildError.h" | ||||
| #include "VersionBuilder.h" | ||||
|  | ||||
| @@ -54,7 +54,7 @@ bool MinecraftVersion::isMinecraftVersion() | ||||
|  | ||||
| // 1. assume the local file is good. load, check. If it's good, apply. | ||||
| // 2. if discrepancies are found, fall out and fail (impossible to apply incomplete version). | ||||
| void MinecraftVersion::applyFileTo(VersionFinal *version) | ||||
| void MinecraftVersion::applyFileTo(InstanceVersion *version) | ||||
| { | ||||
| 	QFileInfo versionFile(QString("versions/%1/%1.dat").arg(m_descriptor)); | ||||
| 	 | ||||
| @@ -62,7 +62,7 @@ void MinecraftVersion::applyFileTo(VersionFinal *version) | ||||
| 	versionObj->applyTo(version); | ||||
| } | ||||
|  | ||||
| void MinecraftVersion::applyTo(VersionFinal *version) | ||||
| void MinecraftVersion::applyTo(InstanceVersion *version) | ||||
| { | ||||
| 	// do we have this one cached? | ||||
| 	if (m_versionSource == Local) | ||||
|   | ||||
| @@ -24,7 +24,7 @@ | ||||
| #include "VersionFile.h" | ||||
| #include "VersionSource.h" | ||||
|  | ||||
| class VersionFinal; | ||||
| class InstanceVersion; | ||||
| class MinecraftVersion; | ||||
| typedef std::shared_ptr<MinecraftVersion> MinecraftVersionPtr; | ||||
|  | ||||
| @@ -37,7 +37,7 @@ public: /* methods */ | ||||
| 	virtual QString typeString() const override; | ||||
| 	virtual bool hasJarMods() override; | ||||
| 	virtual bool isMinecraftVersion() override; | ||||
| 	virtual void applyTo(VersionFinal *version) override; | ||||
| 	virtual void applyTo(InstanceVersion *version) override; | ||||
| 	virtual int getOrder(); | ||||
| 	virtual void setOrder(int order); | ||||
| 	virtual QList<JarmodPtr> getJarMods() override; | ||||
| @@ -55,7 +55,7 @@ public: /* methods */ | ||||
| 	} | ||||
|  | ||||
| private: /* methods */ | ||||
| 	void applyFileTo(VersionFinal *version); | ||||
| 	void applyFileTo(InstanceVersion *version); | ||||
|  | ||||
| public: /* data */ | ||||
| 	/// The URL that this version will be downloaded from. maybe. | ||||
|   | ||||
| @@ -28,7 +28,7 @@ | ||||
|  | ||||
| #include "MultiMC.h" | ||||
| #include "logic/minecraft/VersionBuilder.h" | ||||
| #include "logic/minecraft/VersionFinal.h" | ||||
| #include "logic/minecraft/InstanceVersion.h" | ||||
| #include "logic/minecraft/OneSixRule.h" | ||||
| #include "logic/minecraft/VersionPatch.h" | ||||
| #include "logic/minecraft/VersionFile.h" | ||||
| @@ -44,7 +44,7 @@ VersionBuilder::VersionBuilder() | ||||
| { | ||||
| } | ||||
|  | ||||
| void VersionBuilder::build(VersionFinal *version, OneSixInstance *instance, | ||||
| void VersionBuilder::build(InstanceVersion *version, OneSixInstance *instance, | ||||
| 						   const QStringList &external) | ||||
| { | ||||
| 	VersionBuilder builder; | ||||
| @@ -54,7 +54,7 @@ void VersionBuilder::build(VersionFinal *version, OneSixInstance *instance, | ||||
| 	builder.buildInternal(); | ||||
| } | ||||
|  | ||||
| void VersionBuilder::readJsonAndApplyToVersion(VersionFinal *version, const QJsonObject &obj) | ||||
| void VersionBuilder::readJsonAndApplyToVersion(InstanceVersion *version, const QJsonObject &obj) | ||||
| { | ||||
| 	VersionBuilder builder; | ||||
| 	builder.m_version = version; | ||||
| @@ -312,10 +312,9 @@ bool VersionBuilder::writeOverrideOrders(const QMap<QString, int> &order, | ||||
| 	QJsonObject obj; | ||||
| 	for (auto it = order.cbegin(); it != order.cend(); ++it) | ||||
| 	{ | ||||
| 		if (it.key().startsWith("org.multimc.")) | ||||
| 		{ | ||||
| 		int order = it.value(); | ||||
| 		if(order < 0) | ||||
| 			continue; | ||||
| 		} | ||||
| 		obj.insert(it.key(), it.value()); | ||||
| 	} | ||||
| 	QFile orderFile(instance->instanceRoot() + "/order.json"); | ||||
|   | ||||
| @@ -19,7 +19,7 @@ | ||||
| #include <QMap> | ||||
| #include "VersionFile.h" | ||||
|  | ||||
| class VersionFinal; | ||||
| class InstanceVersion; | ||||
| class OneSixInstance; | ||||
| class QJsonObject; | ||||
| class QFileInfo; | ||||
| @@ -28,8 +28,8 @@ class VersionBuilder | ||||
| { | ||||
| 	VersionBuilder(); | ||||
| public: | ||||
| 	static void build(VersionFinal *version, OneSixInstance *instance, const QStringList &external); | ||||
| 	static void readJsonAndApplyToVersion(VersionFinal *version, const QJsonObject &obj); | ||||
| 	static void build(InstanceVersion *version, OneSixInstance *instance, const QStringList &external); | ||||
| 	static void readJsonAndApplyToVersion(InstanceVersion *version, const QJsonObject &obj); | ||||
| 	static VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, bool isFTB = false); | ||||
| 	static VersionFilePtr parseBinaryJsonFile(const QFileInfo &fileInfo); | ||||
| 	 | ||||
| @@ -37,7 +37,7 @@ public: | ||||
| 	static bool writeOverrideOrders(const QMap<QString, int> &order, OneSixInstance *instance); | ||||
|  | ||||
| private: | ||||
| 	VersionFinal *m_version; | ||||
| 	InstanceVersion *m_version; | ||||
| 	OneSixInstance *m_instance; | ||||
| 	QStringList external_patches; | ||||
| 	QDir instance_root; | ||||
|   | ||||
| @@ -6,7 +6,7 @@ | ||||
|  | ||||
| #include "logic/minecraft/VersionFile.h" | ||||
| #include "logic/minecraft/OneSixLibrary.h" | ||||
| #include "logic/minecraft/VersionFinal.h" | ||||
| #include "logic/minecraft/InstanceVersion.h" | ||||
| #include "logic/minecraft/JarMod.h" | ||||
| #include "ParseUtils.h" | ||||
|  | ||||
| @@ -266,7 +266,7 @@ bool VersionFile::hasJarMods() | ||||
| 	return !jarMods.isEmpty(); | ||||
| } | ||||
|  | ||||
| void VersionFile::applyTo(VersionFinal *version) | ||||
| void VersionFile::applyTo(InstanceVersion *version) | ||||
| { | ||||
| 	if (minimumLauncherVersion != -1) | ||||
| 	{ | ||||
|   | ||||
| @@ -11,7 +11,7 @@ | ||||
| #include "OneSixLibrary.h" | ||||
| #include "JarMod.h" | ||||
|  | ||||
| class VersionFinal; | ||||
| class InstanceVersion; | ||||
| struct VersionFile; | ||||
|  | ||||
| typedef std::shared_ptr<VersionFile> VersionFilePtr; | ||||
| @@ -22,7 +22,7 @@ public: /* methods */ | ||||
| 								   const bool requireOrder, const bool isFTB = false); | ||||
| 	QJsonDocument toJson(bool saveOrder); | ||||
|  | ||||
| 	virtual void applyTo(VersionFinal *version) override; | ||||
| 	virtual void applyTo(InstanceVersion *version) override; | ||||
| 	virtual bool isMinecraftVersion() override; | ||||
| 	virtual bool hasJarMods() override; | ||||
| 	virtual int getOrder() override | ||||
|   | ||||
| @@ -4,12 +4,12 @@ | ||||
| #include <QList> | ||||
| #include "JarMod.h" | ||||
|  | ||||
| class VersionFinal; | ||||
| class InstanceVersion; | ||||
| class VersionPatch | ||||
| { | ||||
| public: | ||||
| 	virtual ~VersionPatch(){}; | ||||
| 	virtual void applyTo(VersionFinal *version) = 0; | ||||
| 	virtual void applyTo(InstanceVersion *version) = 0; | ||||
| 	 | ||||
| 	virtual bool isMinecraftVersion() = 0; | ||||
| 	virtual bool hasJarMods() = 0; | ||||
|   | ||||
| @@ -21,7 +21,6 @@ | ||||
| #include "MD5EtagDownload.h" | ||||
| #include "CacheDownload.h" | ||||
| #include "HttpMetaCache.h" | ||||
| //#include "logic/forge/ForgeXzDownload.h" | ||||
| #include "logic/tasks/ProgressProvider.h" | ||||
|  | ||||
| class NetJob; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user