From d6ab4b4a7fa9451963406911477316a1bc2c1cae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Wed, 5 Jul 2017 18:02:49 +0200 Subject: [PATCH] NOISSUE rearrange global initialization --- api/logic/Env.cpp | 42 +- api/logic/Env.h | 14 +- api/logic/minecraft/legacy/LegacyUpdate.cpp | 2 +- application/MultiMC.cpp | 838 ++++++++++---------- application/MultiMC.h | 27 +- 5 files changed, 426 insertions(+), 497 deletions(-) diff --git a/api/logic/Env.cpp b/api/logic/Env.cpp index 59d4c4a85..3a4847033 100644 --- a/api/logic/Env.cpp +++ b/api/logic/Env.cpp @@ -10,17 +10,18 @@ #include "tasks/Task.h" #include "meta/Index.h" #include "FileSystem.h" +#include "minecraft/legacy/LwjglVersionList.h" #include -class Env::Private +struct Env::Private { -public: QNetworkAccessManager m_qnam; shared_qobject_ptr m_metacache; std::shared_ptr m_iconlist; - QMap> m_versionLists; shared_qobject_ptr m_metadataIndex; + // FIXME: replace with mojang format LWJGL in meta store + std::shared_ptr m_lwjgllist; QString m_jarsPath; }; @@ -75,32 +76,6 @@ void Env::registerIconList(std::shared_ptr iconlist) d->m_iconlist = iconlist; } -BaseVersionPtr Env::getVersion(QString component, QString version) -{ - auto list = getVersionList(component); - if(!list) - { - return nullptr; - } - return list->findVersion(version); -} - -std::shared_ptr< BaseVersionList > Env::getVersionList(QString component) -{ - auto iter = d->m_versionLists.find(component); - if(iter != d->m_versionLists.end()) - { - return *iter; - } - //return std::make_shared(); - return nullptr; -} - -void Env::registerVersionList(QString name, std::shared_ptr< BaseVersionList > vlist) -{ - d->m_versionLists[name] = vlist; -} - shared_qobject_ptr Env::metadataIndex() { if (!d->m_metadataIndex) @@ -207,4 +182,13 @@ void Env::setJarsPath(const QString& path) d->m_jarsPath = path; } +LWJGLVersionList *Env::getLegacyLWJGL() +{ + if(!d->m_lwjgllist) + { + d->m_lwjgllist.reset(new LWJGLVersionList()); + } + return d->m_lwjgllist.get(); +} + #include "Env.moc" diff --git a/api/logic/Env.h b/api/logic/Env.h index 08b1dd0db..d42f13ceb 100644 --- a/api/logic/Env.h +++ b/api/logic/Env.h @@ -13,6 +13,7 @@ class QNetworkAccessManager; class HttpMetaCache; class BaseVersionList; class BaseVersion; +class LWJGLVersionList; namespace Meta { @@ -24,11 +25,12 @@ class Index; #endif #define ENV (Env::getInstance()) + class MULTIMC_LOGIC_EXPORT Env { friend class MultiMC; private: - class Private; + struct Private; Env(); ~Env(); static void dispose(); @@ -47,18 +49,12 @@ public: /// Updates the application proxy settings from the settings object. void updateProxySettings(QString proxyTypeStr, QString addr, int port, QString user, QString password); - /// get a version list by name - std::shared_ptr getVersionList(QString component); - - /// get a version by list name and version name - std::shared_ptr getVersion(QString component, QString version); - - void registerVersionList(QString name, std::shared_ptr vlist); - void registerIconList(std::shared_ptr iconlist); shared_qobject_ptr metadataIndex(); + LWJGLVersionList *getLegacyLWJGL(); + QString getJarsPath(); void setJarsPath(const QString & path); protected: diff --git a/api/logic/minecraft/legacy/LegacyUpdate.cpp b/api/logic/minecraft/legacy/LegacyUpdate.cpp index e263d0def..6ba0825d6 100644 --- a/api/logic/minecraft/legacy/LegacyUpdate.cpp +++ b/api/logic/minecraft/legacy/LegacyUpdate.cpp @@ -164,7 +164,7 @@ void LegacyUpdate::lwjglStart() { LegacyInstance *inst = (LegacyInstance *)m_inst; - auto list = std::dynamic_pointer_cast(ENV.getVersionList("org.lwjgl.legacy")); + auto list = ENV.getLegacyLWJGL(); if (!list->isLoaded()) { setStatus(tr("Checking the LWJGL version list...")); diff --git a/application/MultiMC.cpp b/application/MultiMC.cpp index c78a536e4..232380c43 100644 --- a/application/MultiMC.cpp +++ b/application/MultiMC.cpp @@ -40,9 +40,6 @@ #include #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" @@ -90,6 +87,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 +224,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 +261,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 - { - m_peerInstance->sendMessage(m_instanceIdToLaunch, 2000); - } - m_status = MultiMC::Succeeded; - return; } + // 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(new QFile(logBase.arg(0))); + if(!logFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) + { + 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; + } + 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(); @@ -274,47 +335,33 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv) m_rootPath = foo.absolutePath(); #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 -#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; - } #ifdef MULTIMC_JARS_LOCATION - ENV.setJarsPath( TOSTRING(MULTIMC_JARS_LOCATION) ); + ENV.setJarsPath( TOSTRING(MULTIMC_JARS_LOCATION) ); #endif + 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() << "<> Paths set."; + } + do // once { if(m_liveCheck) @@ -336,24 +383,257 @@ 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); + + 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); + + // 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(tr("Settings")); + m_globalSettingsProvider->addPage(); + m_globalSettingsProvider->addPage(); + m_globalSettingsProvider->addPage(); + m_globalSettingsProvider->addPage(); + m_globalSettingsProvider->addPage(); + m_globalSettingsProvider->addPage(); + m_globalSettingsProvider->addPage(); + m_globalSettingsProvider->addPage(); + } + 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(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 = 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); + 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(); + 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 +646,67 @@ 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, SIGNAL(aboutToQuit()), SLOT(onExit())); + connect(this, &MultiMC::aboutToQuit, [this](){ + if(m_instances) + { + // m_instances->saveGroupList(); + } + if(logFile) + { + logFile->flush(); + logFile->close(); + } + }); - setIconTheme(settings()->get("IconTheme").toString()); - setApplicationTheme(settings()->get("ApplicationTheme").toString(), true); + { + setIconTheme(settings()->get("IconTheme").toString()); + qDebug() << "<> Icon theme set."; + setApplicationTheme(settings()->get("ApplicationTheme").toString(), true); + qDebug() << "<> Application theme set."; + } - initAnalytics(); + // Initialize analytics + { + 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; + } if(createSetupWizard()) { @@ -461,6 +794,7 @@ void MultiMC::performMainStartupAction() auto inst = instances()->getInstanceById(m_instanceIdToLaunch); if(inst) { + qDebug() << "<> Instance launching:" << m_instanceIdToLaunch; launch(inst, true, nullptr); return; } @@ -469,6 +803,7 @@ void MultiMC::performMainStartupAction() { // normal main window showMainWindow(false); + qDebug() << "<> Main window shown."; } } @@ -515,149 +850,11 @@ 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(); - 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(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 +871,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(tr("Settings")); - m_globalSettingsProvider->addPage(); - m_globalSettingsProvider->addPage(); - m_globalSettingsProvider->addPage(); - m_globalSettingsProvider->addPage(); - m_globalSettingsProvider->addPage(); - m_globalSettingsProvider->addPage(); - m_globalSettingsProvider->addPage(); - m_globalSettingsProvider->addPage(); - } -} - -void MultiMC::initMCEdit() -{ - m_mcedit.reset(new MCEditTool(m_settings)); -} - -void MultiMC::initLegacyLwjgl() -{ - auto list = lwjgllist(); -} - std::shared_ptr MultiMC::translations() { return m_translations; } -std::shared_ptr MultiMC::lwjgllist() -{ - if (!m_lwjgllist) - { - m_lwjgllist.reset(new LWJGLVersionList()); - ENV.registerVersionList("org.lwjgl.legacy", m_lwjgllist); - } - return m_lwjgllist; -} - std::shared_ptr MultiMC::javalist() { if (!m_javalist) { m_javalist.reset(new JavaInstallList()); - ENV.registerVersionList("com.java", m_javalist); } return m_javalist; } @@ -901,19 +897,6 @@ std::vector MultiMC::getValidApplicationThemes() return ret; } -void MultiMC::initThemes() -{ - auto insertTheme = [this](ITheme * theme) - { - m_themes.insert(std::make_pair(theme->id(), std::unique_ptr(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 +922,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); diff --git a/application/MultiMC.h b/application/MultiMC.h index c9bba2f87..697fee7c3 100644 --- a/application/MultiMC.h +++ b/application/MultiMC.h @@ -18,7 +18,6 @@ class SetupWizard; class FolderInstanceProvider; class GenericPageProvider; class QFile; -class LWJGLVersionList; class HttpMetaCache; class SettingsObject; class InstanceList; @@ -91,7 +90,7 @@ public: } std::shared_ptr translations(); - std::shared_ptr lwjgllist(); + std::shared_ptr javalist(); std::shared_ptr instances() const @@ -144,11 +143,6 @@ public: InstanceWindow *showInstanceWindow(InstancePtr instance, QString page = QString()); MainWindow *showMainWindow(bool minimized = false); - size_t numRunningInstances() - { - return m_runningInstances; - } - void updateIsRunning(bool running); bool updatesAreAllowed(); @@ -160,10 +154,6 @@ public slots: bool kill(InstancePtr instance); private slots: - /** - * Do all the things that should be done before we exit - */ - void onExit(); void on_windowClose(); void messageReceived(const QString & message); void controllerSucceeded(); @@ -172,19 +162,7 @@ private slots: void setupWizardFinished(int status); private: - bool initLogger(); void shutdownLogger(); - void initIcons(); - void initThemes(); - void initGlobalSettings(); - void initTranslations(); - void initNetwork(); - void initInstances(); - void initAccounts(); - void initMCEdit(); - void initAnalytics(); - void initLegacyLwjgl(); - void shutdownAnalytics(); bool createSetupWizard(); void performMainStartupAction(); @@ -205,7 +183,6 @@ private: std::shared_ptr m_icons; std::shared_ptr m_updateChecker; std::shared_ptr m_accounts; - std::shared_ptr m_lwjgllist; std::shared_ptr m_javalist; std::shared_ptr m_translations; std::shared_ptr m_globalSettingsProvider; @@ -217,8 +194,10 @@ private: QString m_rootPath; Status m_status = MultiMC::StartingUp; +#if defined Q_OS_WIN32 // used on Windows to attach the standard IO streams bool consoleAttached = false; +#endif // FIXME: attach to instances instead. struct InstanceXtras