summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--application/ConsoleWindow.cpp8
-rw-r--r--application/ConsoleWindow.h4
-rw-r--r--application/MainWindow.cpp61
-rw-r--r--application/MainWindow.h8
-rw-r--r--application/pages/LogPage.cpp4
-rw-r--r--application/pages/LogPage.h4
-rw-r--r--logic/BaseInstance.h2
-rw-r--r--logic/BaseLauncher.cpp403
-rw-r--r--logic/BaseLauncher.h47
-rw-r--r--logic/NullInstance.h2
-rw-r--r--logic/minecraft/LegacyInstance.cpp2
-rw-r--r--logic/minecraft/LegacyInstance.h2
-rw-r--r--logic/minecraft/OneSixInstance.cpp2
-rw-r--r--logic/minecraft/OneSixInstance.h2
-rw-r--r--logic/tools/BaseProfiler.cpp2
-rw-r--r--logic/tools/BaseProfiler.h4
-rw-r--r--logic/tools/JProfiler.cpp4
-rw-r--r--logic/tools/JVisualVM.cpp4
18 files changed, 303 insertions, 262 deletions
diff --git a/application/ConsoleWindow.cpp b/application/ConsoleWindow.cpp
index 6a3cd6b2..98492414 100644
--- a/application/ConsoleWindow.cpp
+++ b/application/ConsoleWindow.cpp
@@ -53,7 +53,7 @@ private:
BasePage * m_log_page;
};
-ConsoleWindow::ConsoleWindow(BaseLauncher *process, QWidget *parent)
+ConsoleWindow::ConsoleWindow(std::shared_ptr<BaseLauncher> process, QWidget *parent)
: QMainWindow(parent), m_proc(process)
{
MultiMCPlatform::fixWM_CLASS(this);
@@ -129,11 +129,11 @@ ConsoleWindow::ConsoleWindow(BaseLauncher *process, QWidget *parent)
}
// Set up signal connections
- connect(m_proc, SIGNAL(ended(InstancePtr, int, QProcess::ExitStatus)), this,
+ connect(m_proc.get(), SIGNAL(ended(InstancePtr, int, QProcess::ExitStatus)), this,
SLOT(onEnded(InstancePtr, int, QProcess::ExitStatus)));
- connect(m_proc, SIGNAL(prelaunch_failed(InstancePtr, int, QProcess::ExitStatus)), this,
+ connect(m_proc.get(), SIGNAL(prelaunch_failed(InstancePtr, int, QProcess::ExitStatus)), this,
SLOT(onEnded(InstancePtr, int, QProcess::ExitStatus)));
- connect(m_proc, SIGNAL(launch_failed(InstancePtr)), this,
+ connect(m_proc.get(), SIGNAL(launch_failed(InstancePtr)), this,
SLOT(onLaunchFailed(InstancePtr)));
setMayClose(false);
diff --git a/application/ConsoleWindow.h b/application/ConsoleWindow.h
index a5e9c3a4..33ae67c7 100644
--- a/application/ConsoleWindow.h
+++ b/application/ConsoleWindow.h
@@ -26,7 +26,7 @@ class ConsoleWindow : public QMainWindow
Q_OBJECT
public:
- explicit ConsoleWindow(BaseLauncher *proc, QWidget *parent = 0);
+ explicit ConsoleWindow(std::shared_ptr<BaseLauncher> proc, QWidget *parent = 0);
virtual ~ConsoleWindow();
/**
@@ -56,7 +56,7 @@ protected:
void closeEvent(QCloseEvent *);
private:
- BaseLauncher *m_proc = nullptr;
+ std::shared_ptr<BaseLauncher> m_proc;
bool m_mayclose = true;
QSystemTrayIcon *m_trayIcon = nullptr;
PageContainer *m_container = nullptr;
diff --git a/application/MainWindow.cpp b/application/MainWindow.cpp
index 8e43ff0e..eb258d20 100644
--- a/application/MainWindow.cpp
+++ b/application/MainWindow.cpp
@@ -1699,39 +1699,14 @@ void MainWindow::doLaunch(bool online, BaseProfilerFactory *profiler)
}
case AuthSession::PlayableOnline:
{
- // update first if the server actually responded
- if (session->auth_server_online)
- {
- updateInstance(m_selectedInstance, session, profiler);
- }
- else
- {
- launchInstance(m_selectedInstance, session, profiler);
- }
+ launchInstance(m_selectedInstance, session, profiler);
tryagain = false;
}
}
}
}
-void MainWindow::updateInstance(InstancePtr instance, AuthSessionPtr session,
- BaseProfilerFactory *profiler)
-{
- auto updateTask = instance->doUpdate();
- if (!updateTask)
- {
- launchInstance(instance, session, profiler);
- return;
- }
- ProgressDialog tDialog(this);
- connect(updateTask.get(), &Task::succeeded, [this, instance, session, profiler]
- { launchInstance(instance, session, profiler); });
- connect(updateTask.get(), SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString)));
- tDialog.exec(updateTask.get());
-}
-
-void MainWindow::launchInstance(InstancePtr instance, AuthSessionPtr session,
- BaseProfilerFactory *profiler)
+void MainWindow::launchInstance(InstancePtr instance, AuthSessionPtr session, BaseProfilerFactory *profiler)
{
Q_ASSERT_X(instance != NULL, "launchInstance", "instance is NULL");
Q_ASSERT_X(session.get() != nullptr, "launchInstance", "session is NULL");
@@ -1744,35 +1719,43 @@ void MainWindow::launchInstance(InstancePtr instance, AuthSessionPtr session,
return;
}
- BaseLauncher *proc = instance->prepareForLaunch(session);
+ auto proc = instance->prepareForLaunch(session);
if (!proc)
return;
+ proc->setProfiler(profiler);
+
this->hide();
console = new ConsoleWindow(proc);
connect(console, &ConsoleWindow::isClosing, this, &MainWindow::instanceEnded);
+ connect(proc.get(), &BaseLauncher::readyForLaunch, this, &MainWindow::readyForLaunch);
proc->setHeader("MultiMC version: " + BuildConfig.printableVersionString() + "\n\n");
- proc->arm();
+ proc->start();
+}
+
+void MainWindow::readyForLaunch(std::shared_ptr<BaseLauncher> launcher)
+{
+ auto profiler = launcher->getProfiler();
if (!profiler)
{
- proc->launch();
+ launcher->launch();
return;
}
QString error;
if (!profiler->check(&error))
{
- proc->abort();
+ launcher->abort();
QMessageBox::critical(this, tr("Error"), tr("Couldn't start profiler: %1").arg(error));
return;
}
- BaseProfiler *profilerInstance = profiler->createProfiler(instance, this);
+ BaseProfiler *profilerInstance = profiler->createProfiler(launcher->instance(), this);
connect(profilerInstance, &BaseProfiler::readyToLaunch,
- [this, proc](const QString & message)
+ [this, launcher](const QString & message)
{
QMessageBox msg;
msg.setText(tr("The game launch is delayed until you press the "
@@ -1783,10 +1766,10 @@ void MainWindow::launchInstance(InstancePtr instance, AuthSessionPtr session,
msg.addButton(tr("Launch"), QMessageBox::AcceptRole);
msg.setModal(true);
msg.exec();
- proc->launch();
+ launcher->launch();
});
connect(profilerInstance, &BaseProfiler::abortLaunch,
- [this, proc](const QString & message)
+ [this, launcher](const QString & message)
{
QMessageBox msg;
msg.setText(tr("Couldn't start the profiler: %1").arg(message));
@@ -1795,17 +1778,17 @@ void MainWindow::launchInstance(InstancePtr instance, AuthSessionPtr session,
msg.addButton(QMessageBox::Ok);
msg.setModal(true);
msg.exec();
- proc->abort();
+ launcher->abort();
});
- profilerInstance->beginProfiling(proc);
+ profilerInstance->beginProfiling(launcher);
}
-
+/*
void MainWindow::onGameUpdateError(QString error)
{
CustomMessageBox::selectable(this, tr("Error updating instance"), error,
QMessageBox::Warning)->show();
}
-
+*/
void MainWindow::taskStart()
{
// Nothing to do here yet.
diff --git a/application/MainWindow.h b/application/MainWindow.h
index 010db55c..292a8d28 100644
--- a/application/MainWindow.h
+++ b/application/MainWindow.h
@@ -128,12 +128,7 @@ slots:
*/
void launchInstance(InstancePtr instance, AuthSessionPtr session, BaseProfilerFactory *profiler = 0);
- /*!
- * Prepares the given instance for launch with the given account.
- */
- void updateInstance(InstancePtr instance, AuthSessionPtr account, BaseProfilerFactory *profiler = 0);
-
- void onGameUpdateError(QString error);
+ void readyForLaunch(std::shared_ptr<BaseLauncher>);
void taskStart();
void taskEnd();
@@ -196,7 +191,6 @@ private:
class GroupView *view;
InstanceProxyModel *proxymodel;
NetJobPtr skin_download_job;
- MinecraftLauncher *proc;
ConsoleWindow *console;
LabeledToolButton *renameButton;
QToolButton *changeIconButton;
diff --git a/application/pages/LogPage.cpp b/application/pages/LogPage.cpp
index 0b88193c..cdf6b345 100644
--- a/application/pages/LogPage.cpp
+++ b/application/pages/LogPage.cpp
@@ -11,12 +11,12 @@
#include <settings/Setting.h>
#include "GuiUtil.h"
-LogPage::LogPage(BaseLauncher *proc, QWidget *parent)
+LogPage::LogPage(std::shared_ptr<BaseLauncher> proc, QWidget *parent)
: QWidget(parent), ui(new Ui::LogPage), m_process(proc)
{
ui->setupUi(this);
ui->tabWidget->tabBar()->hide();
- connect(m_process, SIGNAL(log(QString, MessageLevel::Enum)), this,
+ connect(m_process.get(), SIGNAL(log(QString, MessageLevel::Enum)), this,
SLOT(write(QString, MessageLevel::Enum)));
// create the format and set its font
diff --git a/application/pages/LogPage.h b/application/pages/LogPage.h
index a420a75f..0bd74846 100644
--- a/application/pages/LogPage.h
+++ b/application/pages/LogPage.h
@@ -33,7 +33,7 @@ class LogPage : public QWidget, public BasePage
Q_OBJECT
public:
- explicit LogPage(BaseLauncher *proc, QWidget *parent = 0);
+ explicit LogPage(std::shared_ptr<BaseLauncher> proc, QWidget *parent = 0);
virtual ~LogPage();
virtual QString displayName() const override
{
@@ -77,7 +77,7 @@ private slots:
private:
Ui::LogPage *ui;
- BaseLauncher *m_process;
+ std::shared_ptr<BaseLauncher> m_process;
int m_last_scroll_value = 0;
bool m_scroll_active = true;
int m_saved_offset = 0;
diff --git a/logic/BaseInstance.h b/logic/BaseInstance.h
index 91d46df1..497431d0 100644
--- a/logic/BaseInstance.h
+++ b/logic/BaseInstance.h
@@ -138,7 +138,7 @@ public:
virtual std::shared_ptr<Task> doUpdate() = 0;
/// returns a valid process, ready for launch with the given account.
- virtual BaseLauncher *prepareForLaunch(AuthSessionPtr account) = 0;
+ virtual std::shared_ptr<BaseLauncher> prepareForLaunch(AuthSessionPtr account) = 0;
/// do any necessary cleanups after the instance finishes. also runs before
/// 'prepareForLaunch'
diff --git a/logic/BaseLauncher.cpp b/logic/BaseLauncher.cpp
index 464a2783..991973e7 100644
--- a/logic/BaseLauncher.cpp
+++ b/logic/BaseLauncher.cpp
@@ -19,6 +19,7 @@
#include "MessageLevel.h"
#include "MMCStrings.h"
#include "java/JavaChecker.h"
+#include "tasks/Task.h"
#include <pathutils.h>
#include <QDebug>
#include <QDir>
@@ -29,14 +30,108 @@
#define IBUS "@im=ibus"
-BaseLauncher* BaseLauncher::create(MinecraftInstancePtr inst)
+void BaseLauncher::initializeEnvironment()
+{
+ // prepare the process environment
+ QProcessEnvironment rawenv = QProcessEnvironment::systemEnvironment();
+
+ QStringList ignored =
+ {
+ "JAVA_ARGS",
+ "CLASSPATH",
+ "CONFIGPATH",
+ "JAVA_HOME",
+ "JRE_HOME",
+ "_JAVA_OPTIONS",
+ "JAVA_OPTIONS",
+ "JAVA_TOOL_OPTIONS"
+ };
+ for(auto key: rawenv.keys())
+ {
+ auto value = rawenv.value(key);
+ // filter out dangerous java crap
+ if(ignored.contains(key))
+ {
+ qDebug() << "Env: ignoring" << key << value;
+ continue;
+ }
+ // filter MultiMC-related things
+ if(key.startsWith("QT_"))
+ {
+ qDebug() << "Env: ignoring" << key << value;
+ continue;
+ }
+#ifdef Q_OS_LINUX
+ // Do not pass LD_* variables to java. They were intended for MultiMC
+ if(key.startsWith("LD_"))
+ {
+ qDebug() << "Env: ignoring" << key << value;
+ continue;
+ }
+ // Strip IBus
+ // IBus is a Linux IME framework. For some reason, it breaks MC?
+ if (key == "XMODIFIERS" && value.contains(IBUS))
+ {
+ QString save = value;
+ value.replace(IBUS, "");
+ qDebug() << "Env: stripped" << IBUS << "from" << save << ":" << value;
+ }
+ if(key == "GAME_PRELOAD")
+ {
+ m_env.insert("LD_PRELOAD", value);
+ continue;
+ }
+ if(key == "GAME_LIBRARY_PATH")
+ {
+ m_env.insert("LD_LIBRARY_PATH", value);
+ continue;
+ }
+#endif
+ qDebug() << "Env: " << key << value;
+ m_env.insert(key, value);
+ }
+#ifdef Q_OS_LINUX
+ // HACK: Workaround for QTBUG42500
+ if(!m_env.contains("LD_LIBRARY_PATH"))
+ {
+ m_env.insert("LD_LIBRARY_PATH", "");
+ }
+#endif
+
+ // export some infos
+ auto variables = getVariables();
+ for (auto it = variables.begin(); it != variables.end(); ++it)
+ {
+ m_env.insert(it.key(), it.value());
+ }
+}
+
+void BaseLauncher::init()
+{
+ initializeEnvironment();
+
+ m_process.setProcessEnvironment(m_env);
+ connect(&m_process, &LoggedProcess::log, this, &BaseLauncher::on_log);
+ connect(&m_process, &LoggedProcess::stateChanged, this, &BaseLauncher::on_state);
+
+ m_prelaunchprocess.setProcessEnvironment(m_env);
+ connect(&m_prelaunchprocess, &LoggedProcess::log, this, &BaseLauncher::on_log);
+ connect(&m_prelaunchprocess, &LoggedProcess::stateChanged, this, &BaseLauncher::on_pre_state);
+
+ m_postlaunchprocess.setProcessEnvironment(m_env);
+ connect(&m_postlaunchprocess, &LoggedProcess::log, this, &BaseLauncher::on_log);
+ connect(&m_postlaunchprocess, &LoggedProcess::stateChanged, this, &BaseLauncher::on_post_state);
+
+ m_instance->setRunning(true);
+}
+
+std::shared_ptr<BaseLauncher> BaseLauncher::create(MinecraftInstancePtr inst)
{
- auto proc = new BaseLauncher(inst);
+ std::shared_ptr<BaseLauncher> proc(new BaseLauncher(inst));
proc->init();
return proc;
}
-
BaseLauncher::BaseLauncher(InstancePtr instance): m_instance(instance)
{
}
@@ -158,126 +253,68 @@ QStringList BaseLauncher::javaArguments() const
return args;
}
-bool BaseLauncher::checkJava(QString JavaPath)
+void BaseLauncher::checkJava()
{
- auto realJavaPath = QStandardPaths::findExecutable(JavaPath);
+ m_javaPath = m_instance->settings()->get("JavaPath").toString();
+ emit log("Java path is:\n" + m_javaPath + "\n\n");
+
+ auto realJavaPath = QStandardPaths::findExecutable(m_javaPath);
if (realJavaPath.isEmpty())
{
emit log(tr("The java binary \"%1\" couldn't be found. You may have to set up java "
- "if Minecraft fails to launch.").arg(JavaPath),
+ "if Minecraft fails to launch.").arg(m_javaPath),
MessageLevel::Warning);
}
QFileInfo javaInfo(realJavaPath);
qlonglong javaUnixTime = javaInfo.lastModified().toMSecsSinceEpoch();
auto storedUnixTime = m_instance->settings()->get("JavaTimestamp").toLongLong();
+ this->m_javaUnixTime = javaUnixTime;
// if they are not the same, check!
if(javaUnixTime != storedUnixTime)
{
- QEventLoop ev;
- auto checker = std::make_shared<JavaChecker>();
+ m_JavaChecker = std::make_shared<JavaChecker>();
bool successful = false;
QString errorLog;
QString version;
emit log(tr("Checking Java version..."), MessageLevel::MultiMC);
- connect(checker.get(), &JavaChecker::checkFinished,
- [&](JavaCheckResult result)
- {
- successful = result.valid;
- errorLog = result.errorLog;
- version = result.javaVersion;
- ev.exit();
- });
- checker->m_path = realJavaPath;
- checker->performCheck();
- ev.exec();
- if(!successful)
- {
- // Error message displayed if java can't start
- emit log(tr("Could not start java:"), MessageLevel::Error);
- auto lines = errorLog.split('\n');
- for(auto line: lines)
- {
- emit log(line, MessageLevel::Error);
- }
- emit log("\nCheck your MultiMC Java settings.", MessageLevel::MultiMC);
- m_instance->cleanupAfterRun();
- emit launch_failed(m_instance);
- // not running, failed
- m_instance->setRunning(false);
- return false;
- }
- emit log(tr("Java version is %1!\n").arg(version), MessageLevel::MultiMC);
- m_instance->settings()->set("JavaVersion", version);
- m_instance->settings()->set("JavaTimestamp", javaUnixTime);
+ connect(m_JavaChecker.get(), &JavaChecker::checkFinished, this, &BaseLauncher::checkJavaFinished);
+ m_JavaChecker->m_path = realJavaPath;
+ m_JavaChecker->performCheck();
}
- return true;
+ preLaunch();
}
-void BaseLauncher::arm()
+void BaseLauncher::checkJavaFinished(JavaCheckResult result)
{
- printHeader();
- emit log("Minecraft folder is:\n" + m_process.workingDirectory() + "\n\n");
-
- /*
- if (!preLaunch())
- {
- emit ended(m_instance, 1, QProcess::CrashExit);
- return;
- }
- */
-
- m_instance->setLastLaunch();
-
- QString JavaPath = m_instance->settings()->get("JavaPath").toString();
- emit log("Java path is:\n" + JavaPath + "\n\n");
-
- if(!checkJava(JavaPath))
- {
- return;
- }
-
- QStringList args = javaArguments();
- QString allArgs = args.join(", ");
- emit log("Java Arguments:\n[" + censorPrivateInfo(allArgs) + "]\n\n");
-
- QString wrapperCommand = m_instance->settings()->get("WrapperCommand").toString();
- if(!wrapperCommand.isEmpty())
+ if(!result.valid)
{
- auto realWrapperCommand = QStandardPaths::findExecutable(wrapperCommand);
- if (realWrapperCommand.isEmpty())
+ // Error message displayed if java can't start
+ emit log(tr("Could not start java:"), MessageLevel::Error);
+ auto lines = result.errorLog.split('\n');
+ for(auto line: lines)
{
- emit log(tr("The wrapper command \"%1\" couldn't be found.").arg(wrapperCommand), MessageLevel::Warning);
- m_instance->cleanupAfterRun();
- emit launch_failed(m_instance);
- m_instance->setRunning(false);
- return;
+ emit log(line, MessageLevel::Error);
}
- emit log("Wrapper command is:\n" + wrapperCommand + "\n\n");
- args.prepend(JavaPath);
- m_process.start(wrapperCommand, args);
- }
- else
- {
- m_process.start(JavaPath, args);
- }
-
- // instantiate the launcher part
- if (!m_process.waitForStarted())
- {
- //: Error message displayed if instace can't start
- emit log(tr("Could not launch minecraft!"), MessageLevel::Error);
+ emit log("\nCheck your MultiMC Java settings.", MessageLevel::MultiMC);
m_instance->cleanupAfterRun();
emit launch_failed(m_instance);
// not running, failed
m_instance->setRunning(false);
return;
}
+ emit log(tr("Java version is %1!\n").arg(result.javaVersion), MessageLevel::MultiMC);
+ m_instance->settings()->set("JavaVersion", result.javaVersion);
+ m_instance->settings()->set("JavaTimestamp", m_javaUnixTime);
+ preLaunch();
+}
- emit log(tr("Minecraft process ID: %1\n\n").arg(m_process.processId()), MessageLevel::MultiMC);
+void BaseLauncher::executeTask()
+{
+ printHeader();
+ emit log("Minecraft folder is:\n" + m_process.workingDirectory() + "\n\n");
- // send the launch script to the launcher part
- m_process.write(launchScript.toUtf8());
+ checkJava();
}
void BaseLauncher::launch()
@@ -293,103 +330,6 @@ void BaseLauncher::abort()
}
-void BaseLauncher::initializeEnvironment()
-{
- // prepare the process environment
- QProcessEnvironment rawenv = QProcessEnvironment::systemEnvironment();
-
- QStringList ignored =
- {
- "JAVA_ARGS",
- "CLASSPATH",
- "CONFIGPATH",
- "JAVA_HOME",
- "JRE_HOME",
- "_JAVA_OPTIONS",
- "JAVA_OPTIONS",
- "JAVA_TOOL_OPTIONS"
- };
- for(auto key: rawenv.keys())
- {
- auto value = rawenv.value(key);
- // filter out dangerous java crap
- if(ignored.contains(key))
- {
- qDebug() << "Env: ignoring" << key << value;
- continue;
- }
- // filter MultiMC-related things
- if(key.startsWith("QT_"))
- {
- qDebug() << "Env: ignoring" << key << value;
- continue;
- }
-#ifdef Q_OS_LINUX
- // Do not pass LD_* variables to java. They were intended for MultiMC
- if(key.startsWith("LD_"))
- {
- qDebug() << "Env: ignoring" << key << value;
- continue;
- }
- // Strip IBus
- // IBus is a Linux IME framework. For some reason, it breaks MC?
- if (key == "XMODIFIERS" && value.contains(IBUS))
- {
- QString save = value;
- value.replace(IBUS, "");
- qDebug() << "Env: stripped" << IBUS << "from" << save << ":" << value;
- }
- if(key == "GAME_PRELOAD")
- {
- m_env.insert("LD_PRELOAD", value);
- continue;
- }
- if(key == "GAME_LIBRARY_PATH")
- {
- m_env.insert("LD_LIBRARY_PATH", value);
- continue;
- }
-#endif
- qDebug() << "Env: " << key << value;
- m_env.insert(key, value);
- }
-#ifdef Q_OS_LINUX
- // HACK: Workaround for QTBUG42500
- if(!m_env.contains("LD_LIBRARY_PATH"))
- {
- m_env.insert("LD_LIBRARY_PATH", "");
- }
-#endif
-
- // export some infos
- auto variables = getVariables();
- for (auto it = variables.begin(); it != variables.end(); ++it)
- {
- m_env.insert(it.key(), it.value());
- }
-}
-
-void BaseLauncher::init()
-{
- initializeEnvironment();
-
- m_process.setProcessEnvironment(m_env);
- connect(&m_process, &LoggedProcess::log, this, &BaseLauncher::on_log);
- connect(&m_process, &LoggedProcess::stateChanged, this, &BaseLauncher::on_state);
-
- m_prelaunchprocess.setProcessEnvironment(m_env);
- connect(&m_prelaunchprocess, &LoggedProcess::log, this, &BaseLauncher::on_log);
- connect(&m_prelaunchprocess, &LoggedProcess::stateChanged, this, &BaseLauncher::on_pre_state);
-
- m_postlaunchprocess.setProcessEnvironment(m_env);
- connect(&m_postlaunchprocess, &LoggedProcess::log, this, &BaseLauncher::on_log);
- connect(&m_postlaunchprocess, &LoggedProcess::stateChanged, this, &BaseLauncher::on_post_state);
-
- // a process has been constructed for the instance. It is running from MultiMC POV
- m_instance->setRunning(true);
-}
-
-
void BaseLauncher::setWorkdir(QString path)
{
QDir mcDir(path);
@@ -468,18 +408,98 @@ void BaseLauncher::on_pre_state(LoggedProcess::State state)
emit prelaunch_failed(m_instance, m_prelaunchprocess.exitCode(), m_prelaunchprocess.exitStatus());
// not running, failed
m_instance->setRunning(false);
+ return;
}
case LoggedProcess::Finished:
{
emit log(tr("Pre-Launch command ran successfully.\n\n"));
- m_instance->reload();
}
case LoggedProcess::Skipped:
+ {
+ m_instance->reload();
+ updateInstance();
+ }
default:
break;
}
}
+void BaseLauncher::updateInstance()
+{
+ m_updateTask = m_instance->doUpdate();
+ if(m_updateTask)
+ {
+ connect(m_updateTask.get(), SIGNAL(finished()), this, SLOT(updateFinished()));
+ m_updateTask->start();
+ return;
+ }
+ makeReady();
+}
+
+void BaseLauncher::updateFinished()
+{
+ if(m_updateTask->successful())
+ {
+ makeReady();
+ }
+ else
+ {
+ QString reason = tr("Instance update failed because: %1.\n\n").arg(m_updateTask->failReason());
+ emit log(reason, MessageLevel::Fatal);
+ m_instance->cleanupAfterRun();
+ emit update_failed(m_instance);
+ emitFailed(reason);
+ m_instance->setRunning(false);
+ }
+}
+
+void BaseLauncher::makeReady()
+{
+ QStringList args = javaArguments();
+ QString allArgs = args.join(", ");
+ emit log("Java Arguments:\n[" + censorPrivateInfo(allArgs) + "]\n\n");
+
+ QString wrapperCommand = m_instance->settings()->get("WrapperCommand").toString();
+ if(!wrapperCommand.isEmpty())
+ {
+ auto realWrapperCommand = QStandardPaths::findExecutable(wrapperCommand);
+ if (realWrapperCommand.isEmpty())
+ {
+ emit log(tr("The wrapper command \"%1\" couldn't be found.").arg(wrapperCommand), MessageLevel::Warning);
+ m_instance->cleanupAfterRun();
+ emit launch_failed(m_instance);
+ m_instance->setRunning(false);
+ return;
+ }
+ emit log("Wrapper command is:\n" + wrapperCommand + "\n\n");
+ args.prepend(m_javaPath);
+ m_process.start(wrapperCommand, args);
+ }
+ else
+ {
+ m_process.start(m_javaPath, args);
+ }
+
+ // instantiate the launcher part
+ if (!m_process.waitForStarted())
+ {
+ //: Error message displayed if instace can't start
+ emit log(tr("Could not launch minecraft!"), MessageLevel::Error);
+ m_instance->cleanupAfterRun();
+ emit launch_failed(m_instance);
+ // not running, failed
+ m_instance->setRunning(false);
+ return;
+ }
+
+ emit log(tr("Minecraft process ID: %1\n\n").arg(m_process.processId()), MessageLevel::MultiMC);
+
+ // send the launch script to the launcher part
+ m_process.write(launchScript.toUtf8());
+
+ emit readyForLaunch(shared_from_this());
+}
+
void BaseLauncher::on_state(LoggedProcess::State state)
{
QProcess::ExitStatus estat = QProcess::NormalExit;
@@ -500,9 +520,14 @@ void BaseLauncher::on_state(LoggedProcess::State state)
// no longer running...
m_instance->setRunning(false);
emit ended(m_instance, exitCode, estat);
+ break;
}
case LoggedProcess::Skipped:
qWarning() << "Illegal game state: Skipped";
+ break;
+ case LoggedProcess::Running:
+ m_instance->setLastLaunch();
+ break;
default:
break;
}
diff --git a/logic/BaseLauncher.h b/logic/BaseLauncher.h
index 59e1fdbb..076d664b 100644
--- a/logic/BaseLauncher.h
+++ b/logic/BaseLauncher.h
@@ -22,8 +22,12 @@
#include "LoggedProcess.h"
/* HACK: MINECRAFT: split! */
#include "minecraft/MinecraftInstance.h"
+#include "java/JavaChecker.h"
+#include "QObjectPtr.h"
+#include "tasks/Task.h"
-class BaseLauncher: public QObject
+class BaseProfilerFactory;
+class BaseLauncher: public Task, public std::enable_shared_from_this<BaseLauncher>
{
Q_OBJECT
protected:
@@ -31,7 +35,7 @@ protected:
void init();
public: /* methods */
- static BaseLauncher *create(MinecraftInstancePtr inst);
+ static std::shared_ptr<BaseLauncher> create(MinecraftInstancePtr inst);
virtual ~BaseLauncher() {};
InstancePtr instance()
@@ -47,6 +51,16 @@ public: /* methods */
void setWorkdir(QString path);
+ BaseProfilerFactory * getProfiler()
+ {
+ return m_profiler;
+ }
+
+ void setProfiler(BaseProfilerFactory * profiler)
+ {
+ m_profiler = profiler;
+ }
+
void killProcess();
qint64 pid();
@@ -54,7 +68,7 @@ public: /* methods */
/**
* @brief prepare the process for launch (for multi-stage launch)
*/
- virtual void arm();
+ virtual void executeTask() override;
/**
* @brief launch the armed instance
@@ -85,6 +99,8 @@ public: /* HACK: MINECRAFT: split! */
protected: /* methods */
void preLaunch();
+ void updateInstance();
+ void makeReady();
void postLaunch();
QString substituteVariables(const QString &cmd) const;
void initializeEnvironment();
@@ -107,6 +123,11 @@ signals:
void prelaunch_failed(InstancePtr, int code, QProcess::ExitStatus status);
/**
+ * @brief emitted when the instance update fails
+ */
+ void update_failed(InstancePtr);
+
+ /**
* @brief emitted when the PostLaunchCommand fails
*/
void postlaunch_failed(InstancePtr, int code, QProcess::ExitStatus status);
@@ -117,6 +138,11 @@ signals:
void ended(InstancePtr, int code, QProcess::ExitStatus status);
/**
+ * @brief emitted when the launch preparations are done
+ */
+ void readyForLaunch(std::shared_ptr<BaseLauncher> launcher);
+
+ /**
* @brief emitted when we want to log something
* @param text the text to log
* @param level the level to log at
@@ -132,6 +158,8 @@ protected slots:
void on_state(LoggedProcess::State state);
void on_post_state(LoggedProcess::State state);
+ void checkJavaFinished(JavaCheckResult result);
+
protected:
InstancePtr m_instance;
@@ -139,16 +167,27 @@ protected:
LoggedProcess m_postlaunchprocess;
LoggedProcess m_process;
QProcessEnvironment m_env;
+ BaseProfilerFactory * m_profiler = nullptr;
bool killed = false;
QString m_header;
+ // for java checker and launch
+ QString m_javaPath;
+ qlonglong m_javaUnixTime;
+
protected: /* HACK: MINECRAFT: split! */
AuthSessionPtr m_session;
QString launchScript;
QString m_nativeFolder;
+ std::shared_ptr<JavaChecker> m_JavaChecker;
+ std::shared_ptr<Task> m_updateTask;
protected: /* HACK: MINECRAFT: split! */
- bool checkJava(QString path);
+ void checkJava();
QStringList javaArguments() const;
+private slots:
+ void updateFinished();
};
+
+class BaseProfilerFactory; \ No newline at end of file
diff --git a/logic/NullInstance.h b/logic/NullInstance.h
index 5e81b2e4..6f737e86 100644
--- a/logic/NullInstance.h
+++ b/logic/NullInstance.h
@@ -43,7 +43,7 @@ public:
{
return instanceRoot();
};
- virtual BaseLauncher* prepareForLaunch(AuthSessionPtr)
+ virtual std::shared_ptr<BaseLauncher> prepareForLaunch(AuthSessionPtr)
{
return nullptr;
}
diff --git a/logic/minecraft/LegacyInstance.cpp b/logic/minecraft/LegacyInstance.cpp
index 0eb379dc..3fe51a4a 100644
--- a/logic/minecraft/LegacyInstance.cpp
+++ b/logic/minecraft/LegacyInstance.cpp
@@ -95,7 +95,7 @@ std::shared_ptr<Task> LegacyInstance::doUpdate()
return std::shared_ptr<Task>(new LegacyUpdate(this, this));
}
-BaseLauncher *LegacyInstance::prepareForLaunch(AuthSessionPtr account)
+std::shared_ptr<BaseLauncher> LegacyInstance::prepareForLaunch(AuthSessionPtr account)
{
QString launchScript;
QIcon icon = ENV.icons()->getIcon(iconKey());
diff --git a/logic/minecraft/LegacyInstance.h b/logic/minecraft/LegacyInstance.h
index 236771f4..a8363e58 100644
--- a/logic/minecraft/LegacyInstance.h
+++ b/logic/minecraft/LegacyInstance.h
@@ -111,7 +111,7 @@ public:
virtual void setShouldUpdate(bool val) override;
virtual std::shared_ptr<Task> doUpdate() override;
- virtual BaseLauncher *prepareForLaunch(AuthSessionPtr account) override;
+ virtual std::shared_ptr<BaseLauncher> prepareForLaunch(AuthSessionPtr account) override;
virtual void cleanupAfterRun() override;
virtual QString getStatusbarDescription() override;
diff --git a/logic/minecraft/OneSixInstance.cpp b/logic/minecraft/OneSixInstance.cpp
index fd3df715..63bc071f 100644
--- a/logic/minecraft/OneSixInstance.cpp
+++ b/logic/minecraft/OneSixInstance.cpp
@@ -123,7 +123,7 @@ QStringList OneSixInstance::processMinecraftArgs(AuthSessionPtr session)
return parts;
}
-BaseLauncher *OneSixInstance::prepareForLaunch(AuthSessionPtr session)
+std::shared_ptr<BaseLauncher> OneSixInstance::prepareForLaunch(AuthSessionPtr session)
{
QString launchScript;
QIcon icon = ENV.icons()->getIcon(iconKey());
diff --git a/logic/minecraft/OneSixInstance.h b/logic/minecraft/OneSixInstance.h
index 5c71687d..3825ba6a 100644
--- a/logic/minecraft/OneSixInstance.h
+++ b/logic/minecraft/OneSixInstance.h
@@ -49,7 +49,7 @@ public:
virtual QString instanceConfigFolder() const override;
virtual std::shared_ptr<Task> doUpdate() override;
- virtual BaseLauncher *prepareForLaunch(AuthSessionPtr account) override;
+ virtual std::shared_ptr<BaseLauncher> prepareForLaunch(AuthSessionPtr account) override;
virtual void cleanupAfterRun() override;
diff --git a/logic/tools/BaseProfiler.cpp b/logic/tools/BaseProfiler.cpp
index cfac47d4..42ed1d93 100644
--- a/logic/tools/BaseProfiler.cpp
+++ b/logic/tools/BaseProfiler.cpp
@@ -7,7 +7,7 @@ BaseProfiler::BaseProfiler(SettingsObjectPtr settings, InstancePtr instance, QOb
{
}
-void BaseProfiler::beginProfiling(BaseLauncher *process)
+void BaseProfiler::beginProfiling(std::shared_ptr<BaseLauncher> process)
{
beginProfilingImpl(process);
}
diff --git a/logic/tools/BaseProfiler.h b/logic/tools/BaseProfiler.h
index 54ba89ce..709c7cb4 100644
--- a/logic/tools/BaseProfiler.h
+++ b/logic/tools/BaseProfiler.h
@@ -15,13 +15,13 @@ public:
public
slots:
- void beginProfiling(BaseLauncher *process);
+ void beginProfiling(std::shared_ptr<BaseLauncher> process);
void abortProfiling();
protected:
QProcess *m_profilerProcess;
- virtual void beginProfilingImpl(BaseLauncher *process) = 0;
+ virtual void beginProfilingImpl(std::shared_ptr<BaseLauncher> process) = 0;
virtual void abortProfilingImpl();
signals:
diff --git a/logic/tools/JProfiler.cpp b/logic/tools/JProfiler.cpp
index 73121239..975345d5 100644
--- a/logic/tools/JProfiler.cpp
+++ b/logic/tools/JProfiler.cpp
@@ -18,7 +18,7 @@ private slots:
void profilerFinished(int exit, QProcess::ExitStatus status);
protected:
- void beginProfilingImpl(BaseLauncher *process);
+ void beginProfilingImpl(std::shared_ptr<BaseLauncher> process);
private:
int listeningPort = 0;
@@ -48,7 +48,7 @@ void JProfiler::profilerFinished(int exit, QProcess::ExitStatus status)
}
}
-void JProfiler::beginProfilingImpl(BaseLauncher *process)
+void JProfiler::beginProfilingImpl(std::shared_ptr<BaseLauncher> process)
{
listeningPort = globalSettings->get("JProfilerPort").toInt();
QProcess *profiler = new QProcess(this);
diff --git a/logic/tools/JVisualVM.cpp b/logic/tools/JVisualVM.cpp
index fbfd858a..a749012b 100644
--- a/logic/tools/JVisualVM.cpp
+++ b/logic/tools/JVisualVM.cpp
@@ -18,7 +18,7 @@ private slots:
void profilerFinished(int exit, QProcess::ExitStatus status);
protected:
- void beginProfilingImpl(BaseLauncher *process);
+ void beginProfilingImpl(std::shared_ptr<BaseLauncher> process);
};
@@ -45,7 +45,7 @@ void JVisualVM::profilerFinished(int exit, QProcess::ExitStatus status)
}
}
-void JVisualVM::beginProfilingImpl(BaseLauncher *process)
+void JVisualVM::beginProfilingImpl(std::shared_ptr<BaseLauncher> process)
{
QProcess *profiler = new QProcess(this);
QStringList profilerArgs =