diff --git a/api/logic/CMakeLists.txt b/api/logic/CMakeLists.txt index a762fb223..db1a7decb 100644 --- a/api/logic/CMakeLists.txt +++ b/api/logic/CMakeLists.txt @@ -213,8 +213,10 @@ set(MINECRAFT_SOURCES minecraft/auth/flows/RefreshTask.cpp minecraft/auth/flows/ValidateTask.h minecraft/auth/flows/ValidateTask.cpp + minecraft/gameoptions/GameOptions.h minecraft/gameoptions/GameOptions.cpp + minecraft/update/AssetUpdateTask.h minecraft/update/AssetUpdateTask.cpp minecraft/update/FMLLibrariesTask.cpp @@ -223,6 +225,7 @@ set(MINECRAFT_SOURCES minecraft/update/FoldersTask.h minecraft/update/LibrariesTask.cpp minecraft/update/LibrariesTask.h + minecraft/launch/ClaimAccount.cpp minecraft/launch/ClaimAccount.h minecraft/launch/CreateServerResourcePacksFolder.cpp @@ -239,12 +242,16 @@ set(MINECRAFT_SOURCES minecraft/launch/PrintInstanceInfo.h minecraft/launch/ReconstructAssets.cpp minecraft/launch/ReconstructAssets.h + minecraft/launch/ScanModFolders.cpp + minecraft/launch/ScanModFolders.h + minecraft/legacy/LegacyModList.h minecraft/legacy/LegacyModList.cpp minecraft/legacy/LegacyInstance.h minecraft/legacy/LegacyInstance.cpp minecraft/legacy/LegacyUpgradeTask.h minecraft/legacy/LegacyUpgradeTask.cpp + minecraft/GradleSpecifier.h minecraft/MinecraftInstance.cpp minecraft/MinecraftInstance.h diff --git a/api/logic/minecraft/MinecraftInstance.cpp b/api/logic/minecraft/MinecraftInstance.cpp index 9ca777985..28073edfd 100644 --- a/api/logic/minecraft/MinecraftInstance.cpp +++ b/api/logic/minecraft/MinecraftInstance.cpp @@ -21,6 +21,7 @@ #include "minecraft/launch/ModMinecraftJar.h" #include "minecraft/launch/ClaimAccount.h" #include "minecraft/launch/ReconstructAssets.h" +#include "minecraft/launch/ScanModFolders.h" #include "java/launch/CheckJava.h" #include "java/JavaUtils.h" #include "meta/Index.h" @@ -550,37 +551,38 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session) out << ""; } - if(loaderModList()->size()) - { - out << "Mods:"; - for(auto & mod: loaderModList()->allMods()) + auto printModList = [&](const QString & label, ModFolderModel & model) { + if(model.size()) { - if(!mod.enabled()) - continue; - if(mod.type() == Mod::MOD_FOLDER) - continue; - // TODO: proper implementation would need to descend into folders. + out << QString("%1:").arg(label); + auto modList = model.allMods(); + std::sort(modList.begin(), modList.end(), [](Mod &a, Mod &b) { + auto aName = a.filename().completeBaseName(); + auto bName = b.filename().completeBaseName(); + return aName.localeAwareCompare(bName) < 0; + }); + for(auto & mod: modList) + { + if(mod.type() == Mod::MOD_FOLDER) + { + out << u8" [📁] " + mod.filename().completeBaseName() + " (folder)"; + continue; + } - out << " " + mod.filename().completeBaseName(); + if(mod.enabled()) { + out << u8" [✔️] " + mod.filename().completeBaseName(); + } + else { + out << u8" [❌] " + mod.filename().completeBaseName() + " (disabled)"; + } + + } + out << ""; } - out << ""; - } + }; - if(coreModList()->size()) - { - out << "Core Mods:"; - for(auto & coremod: coreModList()->allMods()) - { - if(!coremod.enabled()) - continue; - if(coremod.type() == Mod::MOD_FOLDER) - continue; - // TODO: proper implementation would need to descend into folders. - - out << " " + coremod.filename().completeBaseName(); - } - out << ""; - } + printModList("Mods", *(loaderModList().get())); + printModList("Core Mods", *(coreModList().get())); auto & jarMods = profile->getJarMods(); if(jarMods.size()) @@ -827,6 +829,11 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt process->appendStep(new ModMinecraftJar(pptr)); } + // if there are any jar mods + { + process->appendStep(new ScanModFolders(pptr)); + } + // print some instance info here... { process->appendStep(new PrintInstanceInfo(pptr, session)); diff --git a/api/logic/minecraft/MinecraftInstance.h b/api/logic/minecraft/MinecraftInstance.h index dd14664f9..a8f64109d 100644 --- a/api/logic/minecraft/MinecraftInstance.h +++ b/api/logic/minecraft/MinecraftInstance.h @@ -6,7 +6,6 @@ #include #include "multimc_logic_export.h" -class ModsModel; class ModFolderModel; class WorldList; class GameOptions; @@ -68,7 +67,6 @@ public: std::shared_ptr getComponentList() const; ////// Mod Lists ////// - std::shared_ptr modsModel() const; std::shared_ptr loaderModList() const; std::shared_ptr coreModList() const; std::shared_ptr resourcePackList() const; @@ -123,7 +121,6 @@ private: protected: // data std::shared_ptr m_components; - mutable std::shared_ptr m_mods_model; 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/launch/ScanModFolders.cpp b/api/logic/minecraft/launch/ScanModFolders.cpp new file mode 100644 index 000000000..485c3dc41 --- /dev/null +++ b/api/logic/minecraft/launch/ScanModFolders.cpp @@ -0,0 +1,54 @@ +/* Copyright 2013-2019 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 "ScanModFolders.h" +#include "launch/LaunchTask.h" +#include "MMCZip.h" +#include "minecraft/OpSys.h" +#include "FileSystem.h" +#include "minecraft/MinecraftInstance.h" +#include "minecraft/mod/ModFolderModel.h" + +void ScanModFolders::executeTask() +{ + auto m_inst = std::dynamic_pointer_cast(m_parent->instance()); + + auto loaders = m_inst->loaderModList(); + connect(loaders.get(), &ModFolderModel::updateFinished, this, &ScanModFolders::modsDone); + loaders->update(); + + auto cores = m_inst->coreModList(); + connect(cores.get(), &ModFolderModel::updateFinished, this, &ScanModFolders::coreModsDone); + cores->update(); +} + +void ScanModFolders::modsDone() +{ + m_modsDone = true; + checkDone(); +} + +void ScanModFolders::coreModsDone() +{ + m_coreModsDone = true; + checkDone(); +} + +void ScanModFolders::checkDone() +{ + if(m_modsDone && m_coreModsDone) { + emitSucceeded(); + } +} diff --git a/api/logic/minecraft/launch/ScanModFolders.h b/api/logic/minecraft/launch/ScanModFolders.h new file mode 100644 index 000000000..360df98d7 --- /dev/null +++ b/api/logic/minecraft/launch/ScanModFolders.h @@ -0,0 +1,42 @@ +/* Copyright 2013-2019 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 + +class ScanModFolders: public LaunchStep +{ + Q_OBJECT +public: + explicit ScanModFolders(LaunchTask *parent) : LaunchStep(parent) {}; + virtual ~ScanModFolders(){}; + + virtual void executeTask() override; + virtual bool canAbort() const override + { + return false; + } +private slots: + void coreModsDone(); + void modsDone(); +private: + void checkDone(); + +private: // DATA + bool m_modsDone = false; + bool m_coreModsDone = false; +}; diff --git a/api/logic/minecraft/mod/ModFolderModel.cpp b/api/logic/minecraft/mod/ModFolderModel.cpp index 79459dacb..632dd9596 100644 --- a/api/logic/minecraft/mod/ModFolderModel.cpp +++ b/api/logic/minecraft/mod/ModFolderModel.cpp @@ -81,12 +81,12 @@ bool ModFolderModel::update() auto task = new ModFolderLoadTask(m_dir); m_update = task->result(); QThreadPool *threadPool = QThreadPool::globalInstance(); - connect(task, &ModFolderLoadTask::succeeded, this, &ModFolderModel::updateFinished); + connect(task, &ModFolderLoadTask::succeeded, this, &ModFolderModel::finishUpdate); threadPool->start(task); return true; } -void ModFolderModel::updateFinished() +void ModFolderModel::finishUpdate() { QSet currentSet = modsIndex.keys().toSet(); auto & newMods = m_update->mods; @@ -159,7 +159,7 @@ void ModFolderModel::updateFinished() m_update.reset(); - emit changed(); + emit updateFinished(); if(scheduled_update) { scheduled_update = false; @@ -180,11 +180,11 @@ void ModFolderModel::resolveMod(Mod& m) m.setResolving(true, nextResolutionTicket); nextResolutionTicket++; QThreadPool *threadPool = QThreadPool::globalInstance(); - connect(task, &LocalModParseTask::finished, this, &ModFolderModel::modParseFinished); + connect(task, &LocalModParseTask::finished, this, &ModFolderModel::finishModParse); threadPool->start(task); } -void ModFolderModel::modParseFinished(int token) +void ModFolderModel::finishModParse(int token) { auto iter = activeTickets.find(token); if(iter == activeTickets.end()) { @@ -317,7 +317,6 @@ bool ModFolderModel::enableMods(const QModelIndexList& indexes, bool enable) m.enable(enable); emit dataChanged(i, i); } - emit changed(); return true; } @@ -335,7 +334,6 @@ bool ModFolderModel::deleteMods(const QModelIndexList& indexes) Mod &m = mods[i.row()]; m.destroy(); } - emit changed(); return true; } diff --git a/api/logic/minecraft/mod/ModFolderModel.h b/api/logic/minecraft/mod/ModFolderModel.h index 776c0c879..ff56be4a7 100644 --- a/api/logic/minecraft/mod/ModFolderModel.h +++ b/api/logic/minecraft/mod/ModFolderModel.h @@ -116,11 +116,11 @@ public slots: private slots: void directoryChanged(QString path); - void updateFinished(); - void modParseFinished(int token); + void finishUpdate(); + void finishModParse(int token); signals: - void changed(); + void updateFinished(); private: void resolveMod(Mod& m);