aboutsummaryrefslogtreecommitdiff
path: root/application/MultiMC.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'application/MultiMC.cpp')
-rw-r--r--application/MultiMC.cpp214
1 files changed, 188 insertions, 26 deletions
diff --git a/application/MultiMC.cpp b/application/MultiMC.cpp
index 3a9c281e..2dd4f83f 100644
--- a/application/MultiMC.cpp
+++ b/application/MultiMC.cpp
@@ -2,15 +2,19 @@
#include "BuildConfig.h"
#include "MainWindow.h"
#include "InstanceWindow.h"
+
+#include "groupview/AccessibleGroupView.h"
+#include <QAccessible>
+
#include "pages/BasePageProvider.h"
#include "pages/global/MultiMCPage.h"
#include "pages/global/MinecraftPage.h"
#include "pages/global/JavaPage.h"
+#include "pages/global/LanguagePage.h"
#include "pages/global/ProxyPage.h"
#include "pages/global/ExternalToolsPage.h"
#include "pages/global/AccountListPage.h"
#include "pages/global/PasteEEPage.h"
-#include "pages/global/PackagesPage.h"
#include "pages/global/CustomCommandsPage.h"
#include "themes/ITheme.h"
@@ -30,6 +34,7 @@
#include <QNetworkAccessManager>
#include <QTranslator>
#include <QLibraryInfo>
+#include <QList>
#include <QStringList>
#include <QDebug>
#include <QStyleFactory>
@@ -40,7 +45,6 @@
#include <minecraft/auth/MojangAccountList.h>
#include "icons/IconList.h"
#include "net/HttpMetaCache.h"
-#include "net/URLConstants.h"
#include "Env.h"
#include "java/JavaUtils.h"
@@ -65,6 +69,8 @@
#include <ganalytics.h>
#include <sys.h>
+#include "pagedialog/PageDialog.h"
+
#if defined Q_OS_WIN32
#ifndef WIN32_LEAN_AND_MEAN
@@ -139,6 +145,27 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
startTime = QDateTime::currentDateTime();
+#ifdef Q_OS_LINUX
+ {
+ QFile osrelease("/proc/sys/kernel/osrelease");
+ if (osrelease.open(QFile::ReadOnly | QFile::Text)) {
+ QTextStream in(&osrelease);
+ auto contents = in.readAll();
+ if(
+ contents.contains("WSL", Qt::CaseInsensitive) ||
+ contents.contains("Microsoft", Qt::CaseInsensitive)
+ ) {
+ showFatalErrorMessage(
+ "Unsupported system detected!",
+ "Linux-on-Windows distributions are not supported.\n\n"
+ "Please use the Windows MultiMC binary when playing on Windows."
+ );
+ return;
+ }
+ }
+ }
+#endif
+
// Don't quit on hiding the last window
this->setQuitOnLastWindowClosed(false);
@@ -150,23 +177,32 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
// --help
parser.addSwitch("help");
parser.addShortOpt("help", 'h');
- parser.addDocumentation("help", "display this help and exit.");
+ parser.addDocumentation("help", "Display this help and exit.");
// --version
parser.addSwitch("version");
parser.addShortOpt("version", 'V');
- parser.addDocumentation("version", "display program version and exit.");
+ parser.addDocumentation("version", "Display program version and exit.");
// --dir
parser.addOption("dir");
parser.addShortOpt("dir", 'd');
- parser.addDocumentation("dir", "use the supplied folder as MultiMC root instead of "
+ parser.addDocumentation("dir", "Use the supplied folder as MultiMC root instead of "
"the binary location (use '.' for current)");
// --launch
parser.addOption("launch");
parser.addShortOpt("launch", 'l');
- parser.addDocumentation("launch", "launch the specified instance (by instance ID)");
+ parser.addDocumentation("launch", "Launch the specified instance (by instance ID)");
+ // --server
+ parser.addOption("server");
+ parser.addShortOpt("server", 's');
+ parser.addDocumentation("server", "Join the specified server on launch "
+ "(only valid in combination with --launch)");
// --alive
parser.addSwitch("alive");
- parser.addDocumentation("alive", "write a small '" + liveCheckFile + "' file after MultiMC starts");
+ parser.addDocumentation("alive", "Write a small '" + liveCheckFile + "' file after MultiMC starts");
+ // --import
+ parser.addOption("import");
+ parser.addShortOpt("import", 'I');
+ parser.addDocumentation("import", "Import instance from specified zip (local path or URL)");
// parse the arguments
try
@@ -176,8 +212,9 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
catch (const ParsingError &e)
{
std::cerr << "CommandLineError: " << e.what() << std::endl;
- std::cerr << "Try '%1 -h' to get help on MultiMC's command line parameters."
- << std::endl;
+ if(argc > 0)
+ std::cerr << "Try '" << argv[0] << " -h' to get help on MultiMC's command line parameters."
+ << std::endl;
m_status = MultiMC::Failed;
return;
}
@@ -200,7 +237,9 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
}
}
m_instanceIdToLaunch = args["launch"].toString();
+ m_serverToJoin = args["server"].toString();
m_liveCheck = args["alive"].toBool();
+ m_zipToImport = args["import"].toUrl();
QString origcwdPath = QDir::currentPath();
QString binPath = applicationDirPath();
@@ -260,6 +299,13 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
return;
}
+ if(m_instanceIdToLaunch.isEmpty() && !m_serverToJoin.isEmpty())
+ {
+ std::cerr << "--server can only be used in combination with --launch!" << std::endl;
+ m_status = MultiMC::Failed;
+ return;
+ }
+
/*
* Establish the mechanism for communication with an already running MultiMC that uses the same data path.
* If there is one, tell it what the user actually wanted to do and exit.
@@ -272,13 +318,28 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
connect(m_peerInstance, &LocalPeer::messageReceived, this, &MultiMC::messageReceived);
if(m_peerInstance->isClient())
{
+ int timeout = 2000;
+
if(m_instanceIdToLaunch.isEmpty())
{
- m_peerInstance->sendMessage("activate", 2000);
+ m_peerInstance->sendMessage("activate", timeout);
+
+ if(!m_zipToImport.isEmpty())
+ {
+ m_peerInstance->sendMessage("import " + m_zipToImport.toString(), timeout);
+ }
}
else
{
- m_peerInstance->sendMessage(m_instanceIdToLaunch, 2000);
+ if(!m_serverToJoin.isEmpty())
+ {
+ m_peerInstance->sendMessage(
+ "launch-with-server " + m_instanceIdToLaunch + " " + m_serverToJoin, timeout);
+ }
+ else
+ {
+ m_peerInstance->sendMessage("launch " + m_instanceIdToLaunch, timeout);
+ }
}
m_status = MultiMC::Succeeded;
return;
@@ -339,7 +400,7 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
ENV.setJarsPath( TOSTRING(MULTIMC_JARS_LOCATION) );
#endif
- qDebug() << "MultiMC 5, (c) 2013-2018 MultiMC Contributors";
+ qDebug() << "MultiMC 5, (c) 2013-2021 MultiMC Contributors";
qDebug() << "Version : " << BuildConfig.printableVersionString();
qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT;
qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC;
@@ -359,6 +420,10 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
{
qDebug() << "ID of instance to launch : " << m_instanceIdToLaunch;
}
+ if(!m_serverToJoin.isEmpty())
+ {
+ qDebug() << "Address of server to join :" << m_serverToJoin;
+ }
qDebug() << "<> Paths set.";
}
@@ -375,7 +440,7 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
auto payload = appID.toString().toUtf8();
if(check.write(payload) != payload.size())
{
- qWarning() << "Could not write into" << liveCheckFile;
+ qWarning() << "Could not write into" << liveCheckFile << "!";
check.remove();
break;
}
@@ -466,9 +531,18 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
m_settings->registerSetting("JavaTimestamp", 0);
m_settings->registerSetting("JavaArchitecture", "");
m_settings->registerSetting("JavaVersion", "");
+ m_settings->registerSetting("JavaVendor", "");
m_settings->registerSetting("LastHostname", "");
m_settings->registerSetting("JvmArgs", "");
+ // Native library workarounds
+ m_settings->registerSetting("UseNativeOpenAL", false);
+ m_settings->registerSetting("UseNativeGLFW", false);
+
+ // Game time
+ m_settings->registerSetting("ShowGameTime", true);
+ m_settings->registerSetting("RecordGameTime", true);
+
// Minecraft launch method
m_settings->registerSetting("MCLaunchMethod", "LauncherPart");
@@ -517,9 +591,9 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
m_globalSettingsProvider->addPage<MultiMCPage>();
m_globalSettingsProvider->addPage<MinecraftPage>();
m_globalSettingsProvider->addPage<JavaPage>();
+ m_globalSettingsProvider->addPage<LanguagePage>();
m_globalSettingsProvider->addPage<CustomCommandsPage>();
m_globalSettingsProvider->addPage<ProxyPage>();
- // m_globalSettingsProvider->addPage<PackagesPage>();
m_globalSettingsProvider->addPage<ExternalToolsPage>();
m_globalSettingsProvider->addPage<AccountListPage>();
m_globalSettingsProvider->addPage<PasteEEPage>();
@@ -527,6 +601,10 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
qDebug() << "<> Settings loaded.";
}
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::installFactory(groupViewAccessibleFactory);
+#endif /* !QT_NO_ACCESSIBILITY */
+
// load translations
{
m_translations.reset(new TranslationsModel("translations"));
@@ -550,7 +628,8 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
{
":/icons/multimc/32x32/instances/",
":/icons/multimc/50x50/instances/",
- ":/icons/multimc/128x128/instances/"
+ ":/icons/multimc/128x128/instances/",
+ ":/icons/multimc/scalable/instances/"
};
m_icons.reset(new IconList(instFolders, setting->get().toString()));
connect(setting.get(), &Setting::SettingChanged,[&](const Setting &, QVariant value)
@@ -589,12 +668,12 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
{
auto InstDirSetting = m_settings->getSetting("InstanceDir");
// instance path: check for problems with '!' in instance path and warn the user in the log
- // and rememer that we have to show him a dialog when the gui starts (if it does so)
+ // and remember that we have to show him a dialog when the gui starts (if it does so)
QString instDir = InstDirSetting->get().toString();
qDebug() << "Instance path : " << instDir;
if (FS::checkProblemticPathJava(QDir(instDir)))
{
- qWarning() << "Your instance path contains \'!\' and this is known to cause java problems";
+ qWarning() << "Your instance path contains \'!\' and this is known to cause java problems!";
}
m_instances.reset(new InstanceList(m_settings, instDir, this));
connect(InstDirSetting.get(), &Setting::SettingChanged, m_instances.get(), &InstanceList::on_InstFolderChanged);
@@ -790,8 +869,19 @@ void MultiMC::performMainStartupAction()
auto inst = instances()->getInstanceById(m_instanceIdToLaunch);
if(inst)
{
- qDebug() << "<> Instance launching:" << m_instanceIdToLaunch;
- launch(inst, true, nullptr);
+ MinecraftServerTargetPtr serverToJoin = nullptr;
+
+ if(!m_serverToJoin.isEmpty())
+ {
+ serverToJoin.reset(new MinecraftServerTarget(MinecraftServerTarget::parse(m_serverToJoin)));
+ qDebug() << "<> Instance" << m_instanceIdToLaunch << "launching with server" << m_serverToJoin;
+ }
+ else
+ {
+ qDebug() << "<> Instance" << m_instanceIdToLaunch << "launching";
+ }
+
+ launch(inst, true, nullptr, serverToJoin);
return;
}
}
@@ -801,6 +891,11 @@ void MultiMC::performMainStartupAction()
showMainWindow(false);
qDebug() << "<> Main window shown.";
}
+ if(!m_zipToImport.isEmpty())
+ {
+ qDebug() << "<> Importing instance from zip:" << m_zipToImport;
+ m_mainWindow->droppedURLs({ m_zipToImport });
+ }
}
void MultiMC::showFatalErrorMessage(const QString& title, const QString& content)
@@ -837,18 +932,66 @@ void MultiMC::messageReceived(const QString& message)
qDebug() << "Received message" << message << "while still initializing. It will be ignored.";
return;
}
- if(message == "activate")
+
+ QString command = message.section(' ', 0, 0);
+
+ if(command == "activate")
{
showMainWindow();
}
- else
+ else if(command == "import")
+ {
+ QString arg = message.section(' ', 1);
+ if(arg.isEmpty())
+ {
+ qWarning() << "Received" << command << "message without a zip path/URL.";
+ return;
+ }
+ m_mainWindow->droppedURLs({ QUrl(arg) });
+ }
+ else if(command == "launch")
{
- auto inst = instances()->getInstanceById(message);
+ QString arg = message.section(' ', 1);
+ if(arg.isEmpty())
+ {
+ qWarning() << "Received" << command << "message without an instance ID.";
+ return;
+ }
+ auto inst = instances()->getInstanceById(arg);
if(inst)
{
launch(inst, true, nullptr);
}
}
+ else if(command == "launch-with-server")
+ {
+ QString instanceID = message.section(' ', 1, 1);
+ QString serverToJoin = message.section(' ', 2, 2);
+ if(instanceID.isEmpty())
+ {
+ qWarning() << "Received" << command << "message without an instance ID.";
+ return;
+ }
+ if(serverToJoin.isEmpty())
+ {
+ qWarning() << "Received" << command << "message without a server to join.";
+ return;
+ }
+ auto inst = instances()->getInstanceById(instanceID);
+ if(inst)
+ {
+ launch(
+ inst,
+ true,
+ nullptr,
+ std::make_shared<MinecraftServerTarget>(MinecraftServerTarget::parse(serverToJoin))
+ );
+ }
+ }
+ else
+ {
+ qWarning() << "Received invalid message" << message;
+ }
}
void MultiMC::analyticsSettingChanged(const Setting&, QVariant value)
@@ -932,11 +1075,15 @@ bool MultiMC::openJsonEditor(const QString &filename)
}
}
-bool MultiMC::launch(InstancePtr instance, bool online, BaseProfilerFactory *profiler)
-{
+bool MultiMC::launch(
+ InstancePtr instance,
+ bool online,
+ BaseProfilerFactory *profiler,
+ MinecraftServerTargetPtr serverToJoin
+) {
if(m_updateRunning)
{
- qDebug() << "Cannot launch instances while an update is running.";
+ qDebug() << "Cannot launch instances while an update is running. Please try again when updates are completed.";
}
else if(instance->canLaunch())
{
@@ -954,6 +1101,7 @@ bool MultiMC::launch(InstancePtr instance, bool online, BaseProfilerFactory *pro
controller->setInstance(instance);
controller->setOnline(online);
controller->setProfiler(profiler);
+ controller->setServerToJoin(serverToJoin);
if(window)
{
controller->setParentWidget(window);
@@ -985,7 +1133,7 @@ bool MultiMC::kill(InstancePtr instance)
{
if (!instance->isRunning())
{
- qWarning() << "Attempted to kill instance" << instance->id() << "which isn't running.";
+ qWarning() << "Attempted to kill instance" << instance->id() << ", which isn't running.";
return false;
}
auto & extras = m_instanceExtras[instance->id()];
@@ -1085,6 +1233,20 @@ void MultiMC::controllerFailed(const QString& error)
}
}
+void MultiMC::ShowGlobalSettings(class QWidget* parent, QString open_page)
+{
+ if(!m_globalSettingsProvider) {
+ return;
+ }
+ emit globalSettingsAboutToOpen();
+ {
+ SettingsObject::Lock lock(MMC->settings());
+ PageDialog dlg(m_globalSettingsProvider.get(), open_page, parent);
+ dlg.exec();
+ }
+ emit globalSettingsClosed();
+}
+
MainWindow* MultiMC::showMainWindow(bool minimized)
{
if(m_mainWindow)