diff --git a/api/logic/BaseInstance.h b/api/logic/BaseInstance.h index 7b059536..de5d6aff 100644 --- a/api/logic/BaseInstance.h +++ b/api/logic/BaseInstance.h @@ -67,8 +67,6 @@ public: /// virtual destructor to make sure the destruction is COMPLETE virtual ~BaseInstance() {}; - virtual void copy(SettingsObjectPtr newSettings, const QDir &newDir) {} - virtual void init() = 0; /// nuke thoroughly - deletes the instance contents, notifies the list/model which is @@ -222,7 +220,8 @@ public: } } - bool canLaunch() const; + virtual bool canLaunch() const; + virtual bool canEdit() const = 0; virtual bool canExport() const = 0; virtual bool reload(); diff --git a/api/logic/CMakeLists.txt b/api/logic/CMakeLists.txt index 5cd80166..0a65c6e2 100644 --- a/api/logic/CMakeLists.txt +++ b/api/logic/CMakeLists.txt @@ -232,6 +232,8 @@ set(MINECRAFT_SOURCES minecraft/legacy/LegacyModList.cpp minecraft/legacy/LegacyInstance.h minecraft/legacy/LegacyInstance.cpp + minecraft/legacy/LegacyMigrationTask.h + minecraft/legacy/LegacyMigrationTask.cpp minecraft/GradleSpecifier.h minecraft/MinecraftInstance.cpp minecraft/MinecraftInstance.h diff --git a/api/logic/InstanceCopyTask.cpp b/api/logic/InstanceCopyTask.cpp index 65c6b9ff..9ede65f5 100644 --- a/api/logic/InstanceCopyTask.cpp +++ b/api/logic/InstanceCopyTask.cpp @@ -49,9 +49,6 @@ void InstanceCopyTask::copyFinished() auto instanceSettings = std::make_shared(FS::PathCombine(m_stagingPath, "instance.cfg")); instanceSettings->registerSetting("InstanceType", "Legacy"); - // FIXME: and this too? errors??? - m_origInstance->copy(instanceSettings, m_stagingPath); - InstancePtr inst(new NullInstance(m_globalSettings, instanceSettings, m_stagingPath)); inst->setName(m_instName); inst->setIconKey(m_instIcon); diff --git a/api/logic/NullInstance.h b/api/logic/NullInstance.h index 892ecc01..062c6b5c 100644 --- a/api/logic/NullInstance.h +++ b/api/logic/NullInstance.h @@ -57,6 +57,14 @@ public: { return false; } + bool canEdit() const override + { + return false; + } + bool canLaunch() const override + { + return false; + } QStringList verboseDescription(AuthSessionPtr session) override { QStringList out; diff --git a/api/logic/minecraft/MinecraftInstance.h b/api/logic/minecraft/MinecraftInstance.h index ebb22eb1..e172edb4 100644 --- a/api/logic/minecraft/MinecraftInstance.h +++ b/api/logic/minecraft/MinecraftInstance.h @@ -21,6 +21,12 @@ public: QString typeName() const override; QSet traits() override; + + bool canEdit() const override + { + return true; + } + bool canExport() const override { return true; diff --git a/api/logic/minecraft/legacy/LegacyInstance.cpp b/api/logic/minecraft/legacy/LegacyInstance.cpp index 532e8307..95cc4689 100644 --- a/api/logic/minecraft/legacy/LegacyInstance.cpp +++ b/api/logic/minecraft/legacy/LegacyInstance.cpp @@ -272,6 +272,15 @@ QString LegacyInstance::defaultCustomBaseJar() const return FS::PathCombine(binRoot(), "mcbackup.jar"); } +std::shared_ptr LegacyInstance::worldList() const +{ + if (!m_world_list) + { + m_world_list.reset(new WorldList(savesDir())); + } + return m_world_list; +} + QString LegacyInstance::typeName() const { return tr("Legacy"); diff --git a/api/logic/minecraft/legacy/LegacyInstance.h b/api/logic/minecraft/legacy/LegacyInstance.h index 9c5cedd3..5f67cddb 100644 --- a/api/logic/minecraft/legacy/LegacyInstance.h +++ b/api/logic/minecraft/legacy/LegacyInstance.h @@ -22,6 +22,7 @@ class ModList; class LegacyModList; +class WorldList; class Task; /* * WHY: Legacy instances - from MultiMC 3 and 4 - are here only to provide a way to upgrade them to the current format. @@ -74,6 +75,7 @@ public: std::shared_ptr jarModList() const; QList getJarMods() const; + std::shared_ptr worldList() const; /*! * Whether or not the instance's minecraft.jar needs to be rebuilt. @@ -95,6 +97,14 @@ public: virtual QString typeName() const override; + bool canLaunch() const override + { + return false; + } + bool canEdit() const override + { + return true; + } bool canExport() const override { return false; @@ -125,4 +135,5 @@ public: } protected: mutable std::shared_ptr jar_mod_list; + mutable std::shared_ptr m_world_list; }; diff --git a/api/logic/minecraft/legacy/LegacyMigrationTask.cpp b/api/logic/minecraft/legacy/LegacyMigrationTask.cpp new file mode 100644 index 00000000..0d3cef35 --- /dev/null +++ b/api/logic/minecraft/legacy/LegacyMigrationTask.cpp @@ -0,0 +1,51 @@ +#include "LegacyMigrationTask.h" +#include "BaseInstanceProvider.h" +#include "settings/INISettingsObject.h" +#include "FileSystem.h" +#include "NullInstance.h" +#include "pathmatcher/RegexpMatcher.h" +#include + +LegacyMigrationTask::LegacyMigrationTask(SettingsObjectPtr settings, const QString & stagingPath, InstancePtr origInstance) +{ + m_globalSettings = settings; + m_stagingPath = stagingPath; + m_origInstance = origInstance; +} + +void LegacyMigrationTask::executeTask() +{ + setStatus(tr("Copying instance %1").arg(m_origInstance->name())); + + FS::copy folderCopy(m_origInstance->instanceRoot(), m_stagingPath); + folderCopy.followSymlinks(true); + + m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), folderCopy); + connect(&m_copyFutureWatcher, &QFutureWatcher::finished, this, &LegacyMigrationTask::copyFinished); + connect(&m_copyFutureWatcher, &QFutureWatcher::canceled, this, &LegacyMigrationTask::copyAborted); + m_copyFutureWatcher.setFuture(m_copyFuture); +} + +void LegacyMigrationTask::copyFinished() +{ + auto successful = m_copyFuture.result(); + if(!successful) + { + emitFailed(tr("Instance folder copy failed.")); + return; + } + // FIXME: shouldn't this be able to report errors? + auto instanceSettings = std::make_shared(FS::PathCombine(m_stagingPath, "instance.cfg")); + instanceSettings->registerSetting("InstanceType", "Legacy"); + + InstancePtr inst(new NullInstance(m_globalSettings, instanceSettings, m_stagingPath)); + inst->setName(tr("%1 (Migrated)").arg(m_origInstance->name())); + emitSucceeded(); +} + +void LegacyMigrationTask::copyAborted() +{ + emitFailed(tr("Instance folder copy has been aborted.")); + return; +} + diff --git a/api/logic/minecraft/legacy/LegacyMigrationTask.h b/api/logic/minecraft/legacy/LegacyMigrationTask.h new file mode 100644 index 00000000..36cfa240 --- /dev/null +++ b/api/logic/minecraft/legacy/LegacyMigrationTask.h @@ -0,0 +1,37 @@ +#pragma once + +#include "tasks/Task.h" +#include "multimc_logic_export.h" +#include "net/NetJob.h" +#include +#include +#include +#include "settings/SettingsObject.h" +#include "BaseVersion.h" +#include "BaseInstance.h" + + +class BaseInstanceProvider; + +class MULTIMC_LOGIC_EXPORT LegacyMigrationTask : public Task +{ + Q_OBJECT +public: + explicit LegacyMigrationTask(SettingsObjectPtr settings, const QString & stagingPath, InstancePtr origInstance); + +protected: + //! Entry point for tasks. + virtual void executeTask() override; + void copyFinished(); + void copyAborted(); + +private: /* data */ + SettingsObjectPtr m_globalSettings; + InstancePtr m_origInstance; + QString m_stagingPath; + QFuture m_copyFuture; + QFutureWatcher m_copyFutureWatcher; +}; + + + diff --git a/application/InstancePageProvider.h b/application/InstancePageProvider.h index 3b361e3e..1f5a6aef 100644 --- a/application/InstancePageProvider.h +++ b/application/InstancePageProvider.h @@ -50,6 +50,9 @@ public: if(legacy) { values.append(new LegacyUpgradePage(legacy.get())); + values.append(new NotesPage(legacy.get())); + values.append(new WorldListPage(legacy.get(), legacy->worldList(), "worlds", "worlds", tr("Worlds"), "Worlds")); + values.append(new ScreenshotsPage(FS::PathCombine(legacy->minecraftRoot(), "screenshots"))); } auto logMatcher = inst->getLogFileMatcher(); if(logMatcher) diff --git a/application/InstanceWindow.cpp b/application/InstanceWindow.cpp index dd643f47..3c39491b 100644 --- a/application/InstanceWindow.cpp +++ b/application/InstanceWindow.cpp @@ -72,7 +72,7 @@ InstanceWindow::InstanceWindow(InstancePtr instance, QWidget *parent) m_launchOfflineButton = new QPushButton(); horizontalLayout->addWidget(m_launchOfflineButton); m_launchOfflineButton->setText(tr("Launch Offline")); - setKillButton(m_instance->isRunning()); + updateLaunchButtons(); connect(m_launchOfflineButton, SIGNAL(clicked(bool)), SLOT(on_btnLaunchMinecraftOffline_clicked())); m_closeButton = new QPushButton(); @@ -115,14 +115,21 @@ void InstanceWindow::on_instanceStatusChanged(BaseInstance::Status, BaseInstance } } -void InstanceWindow::setKillButton(bool kill) +void InstanceWindow::updateLaunchButtons() { - if(kill) + if(m_instance->isRunning()) { m_launchOfflineButton->setEnabled(false); m_killButton->setText(tr("Kill")); m_killButton->setToolTip(tr("Kill the running instance")); } + else if(!m_instance->canLaunch()) + { + m_launchOfflineButton->setEnabled(false); + m_killButton->setText(tr("Launch")); + m_killButton->setToolTip(tr("Launch the instance")); + m_killButton->setEnabled(false); + } else { m_launchOfflineButton->setEnabled(true); @@ -141,9 +148,9 @@ void InstanceWindow::on_InstanceLaunchTask_changed(std::shared_ptr p m_proc = proc; } -void InstanceWindow::on_RunningState_changed(bool running) +void InstanceWindow::on_RunningState_changed(bool) { - setKillButton(running); + updateLaunchButtons(); m_container->refreshContainer(); } diff --git a/application/InstanceWindow.h b/application/InstanceWindow.h index 8e272e09..7617965e 100644 --- a/application/InstanceWindow.h +++ b/application/InstanceWindow.h @@ -57,7 +57,7 @@ protected: void closeEvent(QCloseEvent *) override; private: - void setKillButton(bool kill); + void updateLaunchButtons(); private: std::shared_ptr m_proc; diff --git a/application/MainWindow.cpp b/application/MainWindow.cpp index 86f0398d..a6732cb0 100644 --- a/application/MainWindow.cpp +++ b/application/MainWindow.cpp @@ -665,8 +665,10 @@ void MainWindow::showInstanceContextMenu(const QPoint &pos) } QMenu myMenu; myMenu.addActions(actions); + /* if (onInstance) myMenu.setEnabled(m_selectedInstance->canLaunch()); + */ myMenu.exec(view->mapToGlobal(pos)); } diff --git a/application/MultiMC.cpp b/application/MultiMC.cpp index 52450b0f..0d3ed9a8 100644 --- a/application/MultiMC.cpp +++ b/application/MultiMC.cpp @@ -969,6 +969,11 @@ bool MultiMC::launch(InstancePtr instance, bool online, BaseProfilerFactory *pro showInstanceWindow(instance, "console"); return true; } + else if (instance->canEdit()) + { + showInstanceWindow(instance); + return true; + } return false; }