diff options
Diffstat (limited to 'application/MultiMC.cpp')
-rw-r--r-- | application/MultiMC.cpp | 879 |
1 files changed, 430 insertions, 449 deletions
diff --git a/application/MultiMC.cpp b/application/MultiMC.cpp index c78a536e..f928d11b 100644 --- a/application/MultiMC.cpp +++ b/application/MultiMC.cpp @@ -11,6 +11,7 @@ #include "pages/global/AccountListPage.h" #include "pages/global/PasteEEPage.h" #include "pages/global/PackagesPage.h" +#include "pages/global/CustomCommandsPage.h" #include "themes/ITheme.h" #include "themes/SystemTheme.h" @@ -36,13 +37,9 @@ #include "dialogs/CustomMessageBox.h" #include "InstanceList.h" #include "FolderInstanceProvider.h" -#include "minecraft/ftb/FTBInstanceProvider.h" #include <minecraft/auth/MojangAccountList.h> #include "icons/IconList.h" -//FIXME: get rid of this -#include "minecraft/legacy/LwjglVersionList.h" - #include "net/HttpMetaCache.h" #include "net/URLConstants.h" #include "Env.h" @@ -61,8 +58,6 @@ #include "translations/TranslationsModel.h" -#include "minecraft/ftb/FTBPlugin.h" - #include <Commandline.h> #include <FileSystem.h> #include <DesktopServices.h> @@ -71,6 +66,7 @@ #include <ganalytics.h> #include <sys.h> + #if defined Q_OS_WIN32 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN @@ -90,6 +86,26 @@ using namespace Commandline; "This usually fixes the problem and you can move the application elsewhere afterwards.\n"\ "\n" +static void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) +{ + const char *levels = "DWCFIS"; + const QString format("%1 %2 %3\n"); + + qint64 msecstotal = MMC->timeSinceStart(); + qint64 seconds = msecstotal / 1000; + qint64 msecs = msecstotal % 1000; + QString foo; + char buf[1025] = {0}; + ::snprintf(buf, 1024, "%5lld.%03lld", seconds, msecs); + + QString out = format.arg(buf).arg(levels[type]).arg(msg); + + MMC->logFile->write(out.toUtf8()); + MMC->logFile->flush(); + QTextStream(stderr) << out.toLocal8Bit(); + fflush(stderr); +} + MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv) { #if defined Q_OS_WIN32 @@ -207,10 +223,7 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv) if (xdgDataHome.isEmpty()) xdgDataHome = QDir::homePath() + QLatin1String("/.local/share"); dataPath = xdgDataHome + "/multimc"; - printf("BLAH %s", xdgDataHome.toStdString().c_str()); - adjustedBy += "XDG standard " + dataPath; - #else dataPath = applicationDirPath(); adjustedBy += "Fallback to binary path " + dataPath; @@ -247,23 +260,70 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv) ); 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. + * We want to initialize this before logging to avoid messing with the log of a potential already running copy. + */ auto appID = ApplicationId::fromPathAndVersion(QDir::currentPath(), BuildConfig.printableVersionString()); - m_peerInstance = new LocalPeer(this, appID); - connect(m_peerInstance, &LocalPeer::messageReceived, this, &MultiMC::messageReceived); - if(m_peerInstance->isClient()) { - if(m_instanceIdToLaunch.isEmpty()) + // FIXME: you can run the same binaries with multiple data dirs and they won't clash. This could cause issues for updates. + m_peerInstance = new LocalPeer(this, appID); + connect(m_peerInstance, &LocalPeer::messageReceived, this, &MultiMC::messageReceived); + if(m_peerInstance->isClient()) { - m_peerInstance->sendMessage("activate", 2000); + if(m_instanceIdToLaunch.isEmpty()) + { + m_peerInstance->sendMessage("activate", 2000); + } + else + { + m_peerInstance->sendMessage(m_instanceIdToLaunch, 2000); + } + m_status = MultiMC::Succeeded; + return; } - else + } + + // init the logger + { + static const QString logBase = "MultiMC-%0.log"; + auto moveFile = [](const QString &oldName, const QString &newName) + { + QFile::remove(newName); + QFile::copy(oldName, newName); + QFile::remove(oldName); + }; + + moveFile(logBase.arg(3), logBase.arg(4)); + moveFile(logBase.arg(2), logBase.arg(3)); + moveFile(logBase.arg(1), logBase.arg(2)); + moveFile(logBase.arg(0), logBase.arg(1)); + + logFile = std::unique_ptr<QFile>(new QFile(logBase.arg(0))); + if(!logFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { - m_peerInstance->sendMessage(m_instanceIdToLaunch, 2000); + showFatalErrorMessage( + "MultiMC data folder is not writable!", + "MultiMC couldn't create a log file - the MultiMC data folder is not writable.\n" + "\n" + #if defined(Q_OS_MAC) + MACOS_HINT + #endif + "Make sure you have write permissions to the MultiMC data folder.\n" + "\n" + "MultiMC cannot continue until you fix this problem." + ); + return; } - m_status = MultiMC::Succeeded; - return; + qInstallMessageHandler(appDebugOutput); + qDebug() << "<> Log initialized."; } + // Set up paths + { + // Root path is used for updates. #ifdef Q_OS_LINUX QDir foo(FS::PathCombine(binPath, "..")); m_rootPath = foo.absolutePath(); @@ -272,48 +332,36 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv) #elif defined(Q_OS_MAC) QDir foo(FS::PathCombine(binPath, "../..")); m_rootPath = foo.absolutePath(); + // on macOS, touch the root to force Finder to reload the .app metadata (and fix any icon change issues) + FS::updateTimestamp(m_rootPath); #endif - // init the logger - if(!initLogger()) - { - showFatalErrorMessage( - "MultiMC data folder is not writable!", - "MultiMC couldn't create a log file - the MultiMC data folder is not writable.\n" - "\n" -#if defined(Q_OS_MAC) - MACOS_HINT +#ifdef MULTIMC_JARS_LOCATION + ENV.setJarsPath( TOSTRING(MULTIMC_JARS_LOCATION) ); #endif - "Make sure you have write permissions to the MultiMC data folder.\n" - "\n" - "MultiMC cannot continue until you fix this problem." - ); - return; - } - qDebug() << "MultiMC 5, (c) 2013-2017 MultiMC Contributors"; - qDebug() << "Version : " << BuildConfig.printableVersionString(); - qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT; - qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC; - if (adjustedBy.size()) - { - qDebug() << "Work dir before adjustment : " << origcwdPath; - qDebug() << "Work dir after adjustment : " << QDir::currentPath(); - qDebug() << "Adjusted by : " << adjustedBy; - } - else - { - qDebug() << "Work dir : " << QDir::currentPath(); - } - qDebug() << "Binary path : " << binPath; - qDebug() << "Application root path : " << m_rootPath; - if(!m_instanceIdToLaunch.isEmpty()) - { - qDebug() << "ID of instance to launch : " << m_instanceIdToLaunch; + qDebug() << "MultiMC 5, (c) 2013-2018 MultiMC Contributors"; + qDebug() << "Version : " << BuildConfig.printableVersionString(); + qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT; + qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC; + if (adjustedBy.size()) + { + qDebug() << "Work dir before adjustment : " << origcwdPath; + qDebug() << "Work dir after adjustment : " << QDir::currentPath(); + qDebug() << "Adjusted by : " << adjustedBy; + } + else + { + qDebug() << "Work dir : " << QDir::currentPath(); + } + qDebug() << "Binary path : " << binPath; + qDebug() << "Application root path : " << m_rootPath; + if(!m_instanceIdToLaunch.isEmpty()) + { + qDebug() << "ID of instance to launch : " << m_instanceIdToLaunch; + } + qDebug() << "<> Paths set."; } -#ifdef MULTIMC_JARS_LOCATION - ENV.setJarsPath( TOSTRING(MULTIMC_JARS_LOCATION) ); -#endif do // once { @@ -336,24 +384,251 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv) } } while(false); - // load settings - initGlobalSettings(); + // Initialize application settings + { + m_settings.reset(new INISettingsObject("multimc.cfg", this)); + // Updates + m_settings->registerSetting("UpdateChannel", BuildConfig.VERSION_CHANNEL); + m_settings->registerSetting("AutoUpdate", true); + + // Theming + m_settings->registerSetting("IconTheme", QString("multimc")); + m_settings->registerSetting("ApplicationTheme", QString("system")); + + // Notifications + m_settings->registerSetting("ShownNotifications", QString()); + + // Remembered state + m_settings->registerSetting("LastUsedGroupForNewInstance", QString()); + + QString defaultMonospace; + int defaultSize = 11; +#ifdef Q_OS_WIN32 + defaultMonospace = "Courier"; + defaultSize = 10; +#elif defined(Q_OS_MAC) + defaultMonospace = "Menlo"; +#else + defaultMonospace = "Monospace"; +#endif + + // resolve the font so the default actually matches + QFont consoleFont; + consoleFont.setFamily(defaultMonospace); + consoleFont.setStyleHint(QFont::Monospace); + consoleFont.setFixedPitch(true); + QFontInfo consoleFontInfo(consoleFont); + QString resolvedDefaultMonospace = consoleFontInfo.family(); + QFont resolvedFont(resolvedDefaultMonospace); + qDebug() << "Detected default console font:" << resolvedDefaultMonospace + << ", substitutions:" << resolvedFont.substitutions().join(','); + + m_settings->registerSetting("ConsoleFont", resolvedDefaultMonospace); + m_settings->registerSetting("ConsoleFontSize", defaultSize); + m_settings->registerSetting("ConsoleMaxLines", 100000); + m_settings->registerSetting("ConsoleOverflowStop", true); + + // Folders + m_settings->registerSetting("InstanceDir", "instances"); + m_settings->registerSetting({"CentralModsDir", "ModsDir"}, "mods"); + m_settings->registerSetting("IconsDir", "icons"); + + // Editors + m_settings->registerSetting("JsonEditor", QString()); + + // Language + m_settings->registerSetting("Language", QString()); + + // Console + m_settings->registerSetting("ShowConsole", false); + m_settings->registerSetting("AutoCloseConsole", false); + m_settings->registerSetting("ShowConsoleOnError", true); + m_settings->registerSetting("LogPrePostOutput", true); + + // Window Size + m_settings->registerSetting({"LaunchMaximized", "MCWindowMaximize"}, false); + m_settings->registerSetting({"MinecraftWinWidth", "MCWindowWidth"}, 854); + m_settings->registerSetting({"MinecraftWinHeight", "MCWindowHeight"}, 480); + + // Proxy Settings + m_settings->registerSetting("ProxyType", "None"); + m_settings->registerSetting({"ProxyAddr", "ProxyHostName"}, "127.0.0.1"); + m_settings->registerSetting("ProxyPort", 8080); + m_settings->registerSetting({"ProxyUser", "ProxyUsername"}, ""); + m_settings->registerSetting({"ProxyPass", "ProxyPassword"}, ""); + + // Memory + m_settings->registerSetting({"MinMemAlloc", "MinMemoryAlloc"}, 512); + m_settings->registerSetting({"MaxMemAlloc", "MaxMemoryAlloc"}, 1024); + m_settings->registerSetting("PermGen", 128); + + // Java Settings + m_settings->registerSetting("JavaPath", ""); + m_settings->registerSetting("JavaTimestamp", 0); + m_settings->registerSetting("JavaArchitecture", ""); + m_settings->registerSetting("JavaVersion", ""); + m_settings->registerSetting("LastHostname", ""); + m_settings->registerSetting("JvmArgs", ""); + + // Minecraft launch method + m_settings->registerSetting("MCLaunchMethod", "LauncherPart"); + + // Wrapper command for launch + m_settings->registerSetting("WrapperCommand", ""); + + // Custom Commands + m_settings->registerSetting({"PreLaunchCommand", "PreLaunchCmd"}, ""); + m_settings->registerSetting({"PostExitCommand", "PostExitCmd"}, ""); + + // The cat + m_settings->registerSetting("TheCat", false); + + m_settings->registerSetting("InstSortMode", "Name"); + m_settings->registerSetting("SelectedInstance", QString()); + + // Window state and geometry + m_settings->registerSetting("MainWindowState", ""); + m_settings->registerSetting("MainWindowGeometry", ""); + + m_settings->registerSetting("ConsoleWindowState", ""); + m_settings->registerSetting("ConsoleWindowGeometry", ""); + + m_settings->registerSetting("SettingsGeometry", ""); + + m_settings->registerSetting("PagedGeometry", ""); + + m_settings->registerSetting("UpdateDialogGeometry", ""); + + // paste.ee API key + m_settings->registerSetting("PasteEEAPIKey", "multimc"); + + if(!BuildConfig.ANALYTICS_ID.isEmpty()) + { + // Analytics + m_settings->registerSetting("Analytics", true); + m_settings->registerSetting("AnalyticsSeen", 0); + m_settings->registerSetting("AnalyticsClientID", QString()); + } + + // Init page provider + { + m_globalSettingsProvider = std::make_shared<GenericPageProvider>(tr("Settings")); + m_globalSettingsProvider->addPage<MultiMCPage>(); + m_globalSettingsProvider->addPage<MinecraftPage>(); + m_globalSettingsProvider->addPage<JavaPage>(); + m_globalSettingsProvider->addPage<CustomCommandsPage>(); + m_globalSettingsProvider->addPage<ProxyPage>(); + // m_globalSettingsProvider->addPage<PackagesPage>(); + m_globalSettingsProvider->addPage<ExternalToolsPage>(); + m_globalSettingsProvider->addPage<AccountListPage>(); + m_globalSettingsProvider->addPage<PasteEEPage>(); + } + qDebug() << "<> Settings loaded."; + } // load translations - initTranslations(); + { + m_translations.reset(new TranslationsModel("translations")); + auto bcp47Name = m_settings->get("Language").toString(); + m_translations->selectLanguage(bcp47Name); + qDebug() << "Your language is" << bcp47Name; + qDebug() << "<> Translations loaded."; + } // initialize the updater if(BuildConfig.UPDATER_ENABLED) { m_updateChecker.reset(new UpdateChecker(BuildConfig.CHANLIST_URL, BuildConfig.VERSION_CHANNEL, BuildConfig.VERSION_BUILD)); + qDebug() << "<> Updater started."; } - initIcons(); - initThemes(); - initInstances(); - initAccounts(); - initNetwork(); - initLegacyLwjgl(); + // Instance icons + { + auto setting = MMC->settings()->getSetting("IconsDir"); + QStringList instFolders = + { + ":/icons/multimc/32x32/instances/", + ":/icons/multimc/50x50/instances/", + ":/icons/multimc/128x128/instances/" + }; + m_icons.reset(new IconList(instFolders, setting->get().toString())); + connect(setting.get(), &Setting::SettingChanged,[&](const Setting &, QVariant value) + { + m_icons->directoryChanged(value.toString()); + }); + ENV.registerIconList(m_icons); + qDebug() << "<> Instance icons intialized."; + } + + // Icon themes + { + // TODO: icon themes and instance icons do not mesh well together. Rearrange and fix discrepancies! + // set icon theme search path! + auto searchPaths = QIcon::themeSearchPaths(); + searchPaths.append("iconthemes"); + QIcon::setThemeSearchPaths(searchPaths); + qDebug() << "<> Icon themes initialized."; + } + + // Initialize widget themes + { + auto insertTheme = [this](ITheme * theme) + { + m_themes.insert(std::make_pair(theme->id(), std::unique_ptr<ITheme>(theme))); + }; + auto darkTheme = new DarkTheme(); + insertTheme(new SystemTheme()); + insertTheme(darkTheme); + insertTheme(new BrightTheme()); + insertTheme(new CustomTheme(darkTheme, "custom")); + qDebug() << "<> Widget themes initialized."; + } + + // initialize and load all instances + { + 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) + 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"; + } + m_instances.reset(new InstanceList(this)); + m_instanceFolder = new FolderInstanceProvider(m_settings, instDir); + connect(InstDirSetting.get(), &Setting::SettingChanged, m_instanceFolder, &FolderInstanceProvider::on_InstFolderChanged); + m_instances->addInstanceProvider(m_instanceFolder); + qDebug() << "Loading Instances..."; + m_instances->loadList(true); + qDebug() << "<> Instances loaded."; + } + + // and accounts + { + m_accounts.reset(new MojangAccountList(this)); + qDebug() << "Loading accounts..."; + m_accounts->setListFilePath("accounts.json", true); + m_accounts->loadList(); + qDebug() << "<> Accounts loaded."; + } + + // init the http meta cache + { + ENV.initHttpMetaCache(); + qDebug() << "<> Cache initialized."; + } + + // init proxy settings + { + QString proxyTypeStr = settings()->get("ProxyType").toString(); + QString addr = settings()->get("ProxyAddr").toString(); + int port = settings()->get("ProxyPort").value<qint16>(); + QString user = settings()->get("ProxyUser").toString(); + QString pass = settings()->get("ProxyPass").toString(); + ENV.updateProxySettings(proxyTypeStr, addr, port, user, pass); + qDebug() << "<> Proxy settings done."; + } // now we have network, download translation updates m_translations->downloadIndex(); @@ -366,14 +641,69 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv) profiler->registerSettings(m_settings); } - initMCEdit(); + // Create the MCEdit thing... why is this here? + { + m_mcedit.reset(new MCEditTool(m_settings)); + } + + connect(this, &MultiMC::aboutToQuit, [this](){ + if(m_instances) + { + // save any remaining instance state + m_instances->saveNow(); + } + if(logFile) + { + logFile->flush(); + logFile->close(); + } + }); + + { + setIconTheme(settings()->get("IconTheme").toString()); + qDebug() << "<> Icon theme set."; + setApplicationTheme(settings()->get("ApplicationTheme").toString(), true); + qDebug() << "<> Application theme set."; + } + + // Initialize analytics + [this]() + { + const int analyticsVersion = 2; + if(BuildConfig.ANALYTICS_ID.isEmpty()) + { + return; + } - connect(this, SIGNAL(aboutToQuit()), SLOT(onExit())); + auto analyticsSetting = m_settings->getSetting("Analytics"); + connect(analyticsSetting.get(), &Setting::SettingChanged, this, &MultiMC::analyticsSettingChanged); + QString clientID = m_settings->get("AnalyticsClientID").toString(); + if(clientID.isEmpty()) + { + clientID = QUuid::createUuid().toString(); + clientID.remove(QLatin1Char('{')); + clientID.remove(QLatin1Char('}')); + m_settings->set("AnalyticsClientID", clientID); + } + m_analytics = new GAnalytics(BuildConfig.ANALYTICS_ID, clientID, analyticsVersion, this); + m_analytics->setLogLevel(GAnalytics::Debug); + m_analytics->setAnonymizeIPs(true); + m_analytics->setNetworkAccessManager(&ENV.qnam()); - setIconTheme(settings()->get("IconTheme").toString()); - setApplicationTheme(settings()->get("ApplicationTheme").toString(), true); + if(m_settings->get("AnalyticsSeen").toInt() < m_analytics->version()) + { + qDebug() << "Analytics info not seen by user yet (or old version)."; + return; + } + if(!m_settings->get("Analytics").toBool()) + { + qDebug() << "Analytics disabled by user."; + return; + } - initAnalytics(); + m_analytics->enable(); + qDebug() << "<> Initialized analytics with tid" << BuildConfig.ANALYTICS_ID; + }(); if(createSetupWizard()) { @@ -461,6 +791,7 @@ void MultiMC::performMainStartupAction() auto inst = instances()->getInstanceById(m_instanceIdToLaunch); if(inst) { + qDebug() << "<> Instance launching:" << m_instanceIdToLaunch; launch(inst, true, nullptr); return; } @@ -469,6 +800,7 @@ void MultiMC::performMainStartupAction() { // normal main window showMainWindow(false); + qDebug() << "<> Main window shown."; } } @@ -481,17 +813,22 @@ void MultiMC::showFatalErrorMessage(const QString& title, const QString& content MultiMC::~MultiMC() { + // kill the other globals. + Env::dispose(); + + // Shut down logger by setting the logger function to nothing + qInstallMessageHandler(nullptr); + #if defined Q_OS_WIN32 + // Detach from Windows console if(consoleAttached) { - const char * endline = "\n"; - auto out = GetStdHandle (STD_OUTPUT_HANDLE); - DWORD written; - WriteConsole(out, endline, strlen(endline), &written, NULL); + fclose(stdout); + fclose(stdin); + fclose(stderr); + FreeConsole(); } #endif - shutdownLogger(); - Env::dispose(); } void MultiMC::messageReceived(const QString& message) @@ -515,149 +852,6 @@ void MultiMC::messageReceived(const QString& message) } } -void MultiMC::initNetwork() -{ - // init the http meta cache - ENV.initHttpMetaCache(); - - // init proxy settings - { - QString proxyTypeStr = settings()->get("ProxyType").toString(); - QString addr = settings()->get("ProxyAddr").toString(); - int port = settings()->get("ProxyPort").value<qint16>(); - QString user = settings()->get("ProxyUser").toString(); - QString pass = settings()->get("ProxyPass").toString(); - ENV.updateProxySettings(proxyTypeStr, addr, port, user, pass); - } -} - -void MultiMC::initTranslations() -{ - m_translations.reset(new TranslationsModel("translations")); - auto bcp47Name = m_settings->get("Language").toString(); - m_translations->selectLanguage(bcp47Name); - qDebug() << "Your language is" << bcp47Name; -} - -void MultiMC::initIcons() -{ - auto setting = MMC->settings()->getSetting("IconsDir"); - QStringList instFolders = - { - ":/icons/multimc/32x32/instances/", - ":/icons/multimc/50x50/instances/", - ":/icons/multimc/128x128/instances/" - }; - m_icons.reset(new IconList(instFolders, setting->get().toString())); - connect(setting.get(), &Setting::SettingChanged,[&](const Setting &, QVariant value) - { - m_icons->directoryChanged(value.toString()); - }); - ENV.registerIconList(m_icons); - - // set icon theme search path! - auto searchPaths = QIcon::themeSearchPaths(); - searchPaths.append("iconthemes"); - QIcon::setThemeSearchPaths(searchPaths); -} - -void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) -{ - const char *levels = "DWCFIS"; - const QString format("%1 %2 %3\n"); - - qint64 msecstotal = MMC->timeSinceStart(); - qint64 seconds = msecstotal / 1000; - qint64 msecs = msecstotal % 1000; - QString foo; - char buf[1025] = {0}; - ::snprintf(buf, 1024, "%5lld.%03lld", seconds, msecs); - - QString out = format.arg(buf).arg(levels[type]).arg(msg); - - MMC->logFile->write(out.toUtf8()); - MMC->logFile->flush(); - QTextStream(stderr) << out.toLocal8Bit(); - fflush(stderr); -} - -static void moveFile(const QString &oldName, const QString &newName) -{ - QFile::remove(newName); - QFile::copy(oldName, newName); - QFile::remove(oldName); -} - -bool MultiMC::initLogger() -{ - static const QString logBase = "MultiMC-%0.log"; - - moveFile(logBase.arg(3), logBase.arg(4)); - moveFile(logBase.arg(2), logBase.arg(3)); - moveFile(logBase.arg(1), logBase.arg(2)); - moveFile(logBase.arg(0), logBase.arg(1)); - - logFile = std::unique_ptr<QFile>(new QFile(logBase.arg(0))); - auto succeeded = logFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate); - if(!succeeded) - { - return false; - } - qInstallMessageHandler(appDebugOutput); - return true; -} - -void MultiMC::shutdownLogger() -{ - qInstallMessageHandler(nullptr); -} - -void MultiMC::initAnalytics() -{ - const int analyticsVersion = 2; - if(BuildConfig.ANALYTICS_ID.isEmpty()) - { - return; - } - - auto analyticsSetting = m_settings->getSetting("Analytics"); - connect(analyticsSetting.get(), &Setting::SettingChanged, this, &MultiMC::analyticsSettingChanged); - QString clientID = m_settings->get("AnalyticsClientID").toString(); - if(clientID.isEmpty()) - { - clientID = QUuid::createUuid().toString(); - clientID.remove(QLatin1Char('{')); - clientID.remove(QLatin1Char('}')); - m_settings->set("AnalyticsClientID", clientID); - } - m_analytics = new GAnalytics(BuildConfig.ANALYTICS_ID, clientID, analyticsVersion, this); - m_analytics->setLogLevel(GAnalytics::Debug); - m_analytics->setAnonymizeIPs(true); - m_analytics->setNetworkAccessManager(&ENV.qnam()); - - if(m_settings->get("AnalyticsSeen").toInt() < m_analytics->version()) - { - qDebug() << "Analytics info not seen by user yet (or old version)."; - return; - } - if(!m_settings->get("Analytics").toBool()) - { - qDebug() << "Analytics disabled by user."; - return; - } - - m_analytics->enable(); - qDebug() << "Initialized analytics with tid" << BuildConfig.ANALYTICS_ID; -} - -void MultiMC::shutdownAnalytics() -{ - if(m_analytics) - { - // TODO: persist unsent messages? send them now? - } -} - void MultiMC::analyticsSettingChanged(const Setting&, QVariant value) { if(!m_analytics) @@ -674,217 +868,16 @@ void MultiMC::analyticsSettingChanged(const Setting&, QVariant value) m_analytics->enable(enabled); } -void MultiMC::initInstances() -{ - 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) - QString instDir = m_settings->get("InstanceDir").toString(); - qDebug() << "Instance path : " << instDir; - if (FS::checkProblemticPathJava(QDir(instDir))) - { - qWarning() << "Your instance path contains \'!\' and this is known to cause java problems"; - } - m_instances.reset(new InstanceList(m_settings, InstDirSetting->get().toString(), this)); - m_instanceFolder = new FolderInstanceProvider(m_settings, instDir); - connect(InstDirSetting.get(), &Setting::SettingChanged, m_instanceFolder, &FolderInstanceProvider::on_InstFolderChanged); - m_instances->addInstanceProvider(m_instanceFolder); - m_instances->addInstanceProvider(new FTBInstanceProvider(m_settings)); - qDebug() << "Loading Instances..."; - m_instances->loadList(true); -} - -void MultiMC::initAccounts() -{ - // and accounts - m_accounts.reset(new MojangAccountList(this)); - qDebug() << "Loading accounts..."; - m_accounts->setListFilePath("accounts.json", true); - m_accounts->loadList(); -} - -void MultiMC::initGlobalSettings() -{ - m_settings.reset(new INISettingsObject("multimc.cfg", this)); - // Updates - m_settings->registerSetting("UpdateChannel", BuildConfig.VERSION_CHANNEL); - m_settings->registerSetting("AutoUpdate", true); - - // Theming - m_settings->registerSetting("IconTheme", QString("multimc")); - m_settings->registerSetting("ApplicationTheme", QString("system")); - - // Notifications - m_settings->registerSetting("ShownNotifications", QString()); - - // Remembered state - m_settings->registerSetting("LastUsedGroupForNewInstance", QString()); - - QString defaultMonospace; - int defaultSize = 11; -#ifdef Q_OS_WIN32 - defaultMonospace = "Courier"; - defaultSize = 10; -#elif defined(Q_OS_MAC) - defaultMonospace = "Menlo"; -#else - defaultMonospace = "Monospace"; -#endif - - // resolve the font so the default actually matches - QFont consoleFont; - consoleFont.setFamily(defaultMonospace); - consoleFont.setStyleHint(QFont::Monospace); - consoleFont.setFixedPitch(true); - QFontInfo consoleFontInfo(consoleFont); - QString resolvedDefaultMonospace = consoleFontInfo.family(); - QFont resolvedFont(resolvedDefaultMonospace); - qDebug() << "Detected default console font:" << resolvedDefaultMonospace - << ", substitutions:" << resolvedFont.substitutions().join(','); - - m_settings->registerSetting("ConsoleFont", resolvedDefaultMonospace); - m_settings->registerSetting("ConsoleFontSize", defaultSize); - m_settings->registerSetting("ConsoleMaxLines", 100000); - m_settings->registerSetting("ConsoleOverflowStop", true); - - FTBPlugin::initialize(m_settings); - - // Folders - m_settings->registerSetting("InstanceDir", "instances"); - m_settings->registerSetting({"CentralModsDir", "ModsDir"}, "mods"); - m_settings->registerSetting({"LWJGLDir", "LwjglDir"}, "lwjgl"); - m_settings->registerSetting("IconsDir", "icons"); - - // Editors - m_settings->registerSetting("JsonEditor", QString()); - - // Language - m_settings->registerSetting("Language", QString()); - - // Console - m_settings->registerSetting("ShowConsole", false); - m_settings->registerSetting("AutoCloseConsole", false); - m_settings->registerSetting("ShowConsoleOnError", true); - m_settings->registerSetting("LogPrePostOutput", true); - - // Console Colors - // m_settings->registerSetting("SysMessageColor", QColor(Qt::blue)); - // m_settings->registerSetting("StdOutColor", QColor(Qt::black)); - // m_settings->registerSetting("StdErrColor", QColor(Qt::red)); - - // Window Size - m_settings->registerSetting({"LaunchMaximized", "MCWindowMaximize"}, false); - m_settings->registerSetting({"MinecraftWinWidth", "MCWindowWidth"}, 854); - m_settings->registerSetting({"MinecraftWinHeight", "MCWindowHeight"}, 480); - - // Proxy Settings - m_settings->registerSetting("ProxyType", "None"); - m_settings->registerSetting({"ProxyAddr", "ProxyHostName"}, "127.0.0.1"); - m_settings->registerSetting("ProxyPort", 8080); - m_settings->registerSetting({"ProxyUser", "ProxyUsername"}, ""); - m_settings->registerSetting({"ProxyPass", "ProxyPassword"}, ""); - - // Memory - m_settings->registerSetting({"MinMemAlloc", "MinMemoryAlloc"}, 512); - m_settings->registerSetting({"MaxMemAlloc", "MaxMemoryAlloc"}, 1024); - m_settings->registerSetting("PermGen", 128); - - // Java Settings - m_settings->registerSetting("JavaPath", ""); - m_settings->registerSetting("JavaTimestamp", 0); - m_settings->registerSetting("JavaArchitecture", ""); - m_settings->registerSetting("JavaVersion", ""); - m_settings->registerSetting("LastHostname", ""); - m_settings->registerSetting("JvmArgs", ""); - - // Minecraft launch method - m_settings->registerSetting("MCLaunchMethod", "LauncherPart"); - - // Wrapper command for launch - m_settings->registerSetting("WrapperCommand", ""); - - // Custom Commands - m_settings->registerSetting({"PreLaunchCommand", "PreLaunchCmd"}, ""); - m_settings->registerSetting({"PostExitCommand", "PostExitCmd"}, ""); - - // The cat - m_settings->registerSetting("TheCat", false); - - m_settings->registerSetting("InstSortMode", "Name"); - m_settings->registerSetting("SelectedInstance", QString()); - - // Window state and geometry - m_settings->registerSetting("MainWindowState", ""); - m_settings->registerSetting("MainWindowGeometry", ""); - - m_settings->registerSetting("ConsoleWindowState", ""); - m_settings->registerSetting("ConsoleWindowGeometry", ""); - - m_settings->registerSetting("SettingsGeometry", ""); - - m_settings->registerSetting("PagedGeometry", ""); - - m_settings->registerSetting("UpdateDialogGeometry", ""); - - // Jar mod nag dialog in version page - m_settings->registerSetting("JarModNagSeen", false); - - // paste.ee API key - m_settings->registerSetting("PasteEEAPIKey", "multimc"); - - if(!BuildConfig.ANALYTICS_ID.isEmpty()) - { - // Analytics - m_settings->registerSetting("Analytics", true); - m_settings->registerSetting("AnalyticsSeen", 0); - m_settings->registerSetting("AnalyticsClientID", QString()); - } - - // Init page provider - { - m_globalSettingsProvider = std::make_shared<GenericPageProvider>(tr("Settings")); - m_globalSettingsProvider->addPage<MultiMCPage>(); - m_globalSettingsProvider->addPage<MinecraftPage>(); - m_globalSettingsProvider->addPage<JavaPage>(); - m_globalSettingsProvider->addPage<ProxyPage>(); - m_globalSettingsProvider->addPage<PackagesPage>(); - m_globalSettingsProvider->addPage<ExternalToolsPage>(); - m_globalSettingsProvider->addPage<AccountListPage>(); - m_globalSettingsProvider->addPage<PasteEEPage>(); - } -} - -void MultiMC::initMCEdit() -{ - m_mcedit.reset(new MCEditTool(m_settings)); -} - -void MultiMC::initLegacyLwjgl() -{ - auto list = lwjgllist(); -} - std::shared_ptr<TranslationsModel> MultiMC::translations() { return m_translations; } -std::shared_ptr<LWJGLVersionList> MultiMC::lwjgllist() -{ - if (!m_lwjgllist) - { - m_lwjgllist.reset(new LWJGLVersionList()); - ENV.registerVersionList("org.lwjgl.legacy", m_lwjgllist); - } - return m_lwjgllist; -} - std::shared_ptr<JavaInstallList> MultiMC::javalist() { if (!m_javalist) { m_javalist.reset(new JavaInstallList()); - ENV.registerVersionList("com.java", m_javalist); } return m_javalist; } @@ -901,19 +894,6 @@ std::vector<ITheme *> MultiMC::getValidApplicationThemes() return ret; } -void MultiMC::initThemes() -{ - auto insertTheme = [this](ITheme * theme) - { - m_themes.insert(std::make_pair(theme->id(), std::unique_ptr<ITheme>(theme))); - }; - auto darkTheme = new DarkTheme(); - insertTheme(new SystemTheme()); - insertTheme(darkTheme); - insertTheme(new BrightTheme()); - insertTheme(new CustomTheme(darkTheme, "custom")); -} - void MultiMC::setApplicationTheme(const QString& name, bool initial) { auto systemPalette = qApp->palette(); @@ -939,19 +919,6 @@ QIcon MultiMC::getThemedIcon(const QString& name) return XdgIcon::fromTheme(name); } -void MultiMC::onExit() -{ - if(m_instances) - { - // m_instances->saveGroupList(); - } - if(logFile) - { - logFile->flush(); - logFile->close(); - } -} - bool MultiMC::openJsonEditor(const QString &filename) { const QString file = QDir::current().absoluteFilePath(filename); @@ -1007,6 +974,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; } @@ -1159,8 +1131,19 @@ MainWindow* MultiMC::showMainWindow(bool minimized) * cd4 = CPU architecture */ QVariantMap customValues; - customValues["cm1"] = m_settings->get("MinMemAlloc"); - customValues["cm2"] = m_settings->get("MaxMemAlloc"); + int min = m_settings->get("MinMemAlloc").toInt(); + int max = m_settings->get("MaxMemAlloc").toInt(); + if(min < max) + { + customValues["cm1"] = min; + customValues["cm2"] = max; + } + else + { + customValues["cm1"] = max; + customValues["cm2"] = min; + } + constexpr uint64_t Mega = 1024ull * 1024ull; int ramSize = int(Sys::getSystemRam() / Mega); qDebug() << "RAM size is" << ramSize << "MB"; @@ -1232,5 +1215,3 @@ void MultiMC::on_windowClose() exit(0); } } - -#include "MultiMC.moc" |