NOISSUE rearrange global initialization

This commit is contained in:
Petr Mrázek 2017-07-05 18:02:49 +02:00
parent 74c455ff35
commit d6ab4b4a7f
5 changed files with 426 additions and 497 deletions

View File

@ -10,17 +10,18 @@
#include "tasks/Task.h" #include "tasks/Task.h"
#include "meta/Index.h" #include "meta/Index.h"
#include "FileSystem.h" #include "FileSystem.h"
#include "minecraft/legacy/LwjglVersionList.h"
#include <QDebug> #include <QDebug>
class Env::Private struct Env::Private
{ {
public:
QNetworkAccessManager m_qnam; QNetworkAccessManager m_qnam;
shared_qobject_ptr<HttpMetaCache> m_metacache; shared_qobject_ptr<HttpMetaCache> m_metacache;
std::shared_ptr<IIconList> m_iconlist; std::shared_ptr<IIconList> m_iconlist;
QMap<QString, std::shared_ptr<BaseVersionList>> m_versionLists;
shared_qobject_ptr<Meta::Index> m_metadataIndex; shared_qobject_ptr<Meta::Index> m_metadataIndex;
// FIXME: replace with mojang format LWJGL in meta store
std::shared_ptr<LWJGLVersionList> m_lwjgllist;
QString m_jarsPath; QString m_jarsPath;
}; };
@ -75,32 +76,6 @@ void Env::registerIconList(std::shared_ptr<IIconList> iconlist)
d->m_iconlist = 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<NullVersionList>();
return nullptr;
}
void Env::registerVersionList(QString name, std::shared_ptr< BaseVersionList > vlist)
{
d->m_versionLists[name] = vlist;
}
shared_qobject_ptr<Meta::Index> Env::metadataIndex() shared_qobject_ptr<Meta::Index> Env::metadataIndex()
{ {
if (!d->m_metadataIndex) if (!d->m_metadataIndex)
@ -207,4 +182,13 @@ void Env::setJarsPath(const QString& path)
d->m_jarsPath = 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" #include "Env.moc"

View File

@ -13,6 +13,7 @@ class QNetworkAccessManager;
class HttpMetaCache; class HttpMetaCache;
class BaseVersionList; class BaseVersionList;
class BaseVersion; class BaseVersion;
class LWJGLVersionList;
namespace Meta namespace Meta
{ {
@ -24,11 +25,12 @@ class Index;
#endif #endif
#define ENV (Env::getInstance()) #define ENV (Env::getInstance())
class MULTIMC_LOGIC_EXPORT Env class MULTIMC_LOGIC_EXPORT Env
{ {
friend class MultiMC; friend class MultiMC;
private: private:
class Private; struct Private;
Env(); Env();
~Env(); ~Env();
static void dispose(); static void dispose();
@ -47,18 +49,12 @@ public:
/// Updates the application proxy settings from the settings object. /// Updates the application proxy settings from the settings object.
void updateProxySettings(QString proxyTypeStr, QString addr, int port, QString user, QString password); void updateProxySettings(QString proxyTypeStr, QString addr, int port, QString user, QString password);
/// get a version list by name
std::shared_ptr<BaseVersionList> getVersionList(QString component);
/// get a version by list name and version name
std::shared_ptr<BaseVersion> getVersion(QString component, QString version);
void registerVersionList(QString name, std::shared_ptr<BaseVersionList> vlist);
void registerIconList(std::shared_ptr<IIconList> iconlist); void registerIconList(std::shared_ptr<IIconList> iconlist);
shared_qobject_ptr<Meta::Index> metadataIndex(); shared_qobject_ptr<Meta::Index> metadataIndex();
LWJGLVersionList *getLegacyLWJGL();
QString getJarsPath(); QString getJarsPath();
void setJarsPath(const QString & path); void setJarsPath(const QString & path);
protected: protected:

View File

@ -164,7 +164,7 @@ void LegacyUpdate::lwjglStart()
{ {
LegacyInstance *inst = (LegacyInstance *)m_inst; LegacyInstance *inst = (LegacyInstance *)m_inst;
auto list = std::dynamic_pointer_cast<LWJGLVersionList>(ENV.getVersionList("org.lwjgl.legacy")); auto list = ENV.getLegacyLWJGL();
if (!list->isLoaded()) if (!list->isLoaded())
{ {
setStatus(tr("Checking the LWJGL version list...")); setStatus(tr("Checking the LWJGL version list..."));

View File

@ -40,9 +40,6 @@
#include <minecraft/auth/MojangAccountList.h> #include <minecraft/auth/MojangAccountList.h>
#include "icons/IconList.h" #include "icons/IconList.h"
//FIXME: get rid of this
#include "minecraft/legacy/LwjglVersionList.h"
#include "net/HttpMetaCache.h" #include "net/HttpMetaCache.h"
#include "net/URLConstants.h" #include "net/URLConstants.h"
#include "Env.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"\ "This usually fixes the problem and you can move the application elsewhere afterwards.\n"\
"\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) MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
{ {
#if defined Q_OS_WIN32 #if defined Q_OS_WIN32
@ -207,10 +224,7 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
if (xdgDataHome.isEmpty()) if (xdgDataHome.isEmpty())
xdgDataHome = QDir::homePath() + QLatin1String("/.local/share"); xdgDataHome = QDir::homePath() + QLatin1String("/.local/share");
dataPath = xdgDataHome + "/multimc"; dataPath = xdgDataHome + "/multimc";
printf("BLAH %s", xdgDataHome.toStdString().c_str());
adjustedBy += "XDG standard " + dataPath; adjustedBy += "XDG standard " + dataPath;
#else #else
dataPath = applicationDirPath(); dataPath = applicationDirPath();
adjustedBy += "Fallback to binary path " + dataPath; adjustedBy += "Fallback to binary path " + dataPath;
@ -247,23 +261,70 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
); );
return; 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()); 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<QFile>(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 #ifdef Q_OS_LINUX
QDir foo(FS::PathCombine(binPath, "..")); QDir foo(FS::PathCombine(binPath, ".."));
m_rootPath = foo.absolutePath(); m_rootPath = foo.absolutePath();
@ -274,47 +335,33 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
m_rootPath = foo.absolutePath(); m_rootPath = foo.absolutePath();
#endif #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 #ifdef MULTIMC_JARS_LOCATION
ENV.setJarsPath( TOSTRING(MULTIMC_JARS_LOCATION) ); ENV.setJarsPath( TOSTRING(MULTIMC_JARS_LOCATION) );
#endif #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 do // once
{ {
if(m_liveCheck) if(m_liveCheck)
@ -336,24 +383,257 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
} }
} while(false); } while(false);
// load settings // Initialize application settings
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);
// 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>();
}
qDebug() << "<> Settings loaded.";
}
// load translations // 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 // initialize the updater
if(BuildConfig.UPDATER_ENABLED) if(BuildConfig.UPDATER_ENABLED)
{ {
m_updateChecker.reset(new UpdateChecker(BuildConfig.CHANLIST_URL, BuildConfig.VERSION_CHANNEL, BuildConfig.VERSION_BUILD)); m_updateChecker.reset(new UpdateChecker(BuildConfig.CHANLIST_URL, BuildConfig.VERSION_CHANNEL, BuildConfig.VERSION_BUILD));
qDebug() << "<> Updater started.";
} }
initIcons(); // Instance icons
initThemes(); {
initInstances(); auto setting = MMC->settings()->getSetting("IconsDir");
initAccounts(); QStringList instFolders =
initNetwork(); {
initLegacyLwjgl(); ":/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 = 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<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 // now we have network, download translation updates
m_translations->downloadIndex(); m_translations->downloadIndex();
@ -366,14 +646,67 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
profiler->registerSettings(m_settings); 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()) if(createSetupWizard())
{ {
@ -461,6 +794,7 @@ void MultiMC::performMainStartupAction()
auto inst = instances()->getInstanceById(m_instanceIdToLaunch); auto inst = instances()->getInstanceById(m_instanceIdToLaunch);
if(inst) if(inst)
{ {
qDebug() << "<> Instance launching:" << m_instanceIdToLaunch;
launch(inst, true, nullptr); launch(inst, true, nullptr);
return; return;
} }
@ -469,6 +803,7 @@ void MultiMC::performMainStartupAction()
{ {
// normal main window // normal main window
showMainWindow(false); 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<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() void MultiMC::shutdownLogger()
{ {
qInstallMessageHandler(nullptr); 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) void MultiMC::analyticsSettingChanged(const Setting&, QVariant value)
{ {
if(!m_analytics) if(!m_analytics)
@ -674,217 +871,16 @@ void MultiMC::analyticsSettingChanged(const Setting&, QVariant value)
m_analytics->enable(enabled); 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() std::shared_ptr<TranslationsModel> MultiMC::translations()
{ {
return m_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() std::shared_ptr<JavaInstallList> MultiMC::javalist()
{ {
if (!m_javalist) if (!m_javalist)
{ {
m_javalist.reset(new JavaInstallList()); m_javalist.reset(new JavaInstallList());
ENV.registerVersionList("com.java", m_javalist);
} }
return m_javalist; return m_javalist;
} }
@ -901,19 +897,6 @@ std::vector<ITheme *> MultiMC::getValidApplicationThemes()
return ret; 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) void MultiMC::setApplicationTheme(const QString& name, bool initial)
{ {
auto systemPalette = qApp->palette(); auto systemPalette = qApp->palette();
@ -939,19 +922,6 @@ QIcon MultiMC::getThemedIcon(const QString& name)
return XdgIcon::fromTheme(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) bool MultiMC::openJsonEditor(const QString &filename)
{ {
const QString file = QDir::current().absoluteFilePath(filename); const QString file = QDir::current().absoluteFilePath(filename);

View File

@ -18,7 +18,6 @@ class SetupWizard;
class FolderInstanceProvider; class FolderInstanceProvider;
class GenericPageProvider; class GenericPageProvider;
class QFile; class QFile;
class LWJGLVersionList;
class HttpMetaCache; class HttpMetaCache;
class SettingsObject; class SettingsObject;
class InstanceList; class InstanceList;
@ -91,7 +90,7 @@ public:
} }
std::shared_ptr<TranslationsModel> translations(); std::shared_ptr<TranslationsModel> translations();
std::shared_ptr<LWJGLVersionList> lwjgllist();
std::shared_ptr<JavaInstallList> javalist(); std::shared_ptr<JavaInstallList> javalist();
std::shared_ptr<InstanceList> instances() const std::shared_ptr<InstanceList> instances() const
@ -144,11 +143,6 @@ public:
InstanceWindow *showInstanceWindow(InstancePtr instance, QString page = QString()); InstanceWindow *showInstanceWindow(InstancePtr instance, QString page = QString());
MainWindow *showMainWindow(bool minimized = false); MainWindow *showMainWindow(bool minimized = false);
size_t numRunningInstances()
{
return m_runningInstances;
}
void updateIsRunning(bool running); void updateIsRunning(bool running);
bool updatesAreAllowed(); bool updatesAreAllowed();
@ -160,10 +154,6 @@ public slots:
bool kill(InstancePtr instance); bool kill(InstancePtr instance);
private slots: private slots:
/**
* Do all the things that should be done before we exit
*/
void onExit();
void on_windowClose(); void on_windowClose();
void messageReceived(const QString & message); void messageReceived(const QString & message);
void controllerSucceeded(); void controllerSucceeded();
@ -172,19 +162,7 @@ private slots:
void setupWizardFinished(int status); void setupWizardFinished(int status);
private: private:
bool initLogger();
void shutdownLogger(); 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(); bool createSetupWizard();
void performMainStartupAction(); void performMainStartupAction();
@ -205,7 +183,6 @@ private:
std::shared_ptr<IconList> m_icons; std::shared_ptr<IconList> m_icons;
std::shared_ptr<UpdateChecker> m_updateChecker; std::shared_ptr<UpdateChecker> m_updateChecker;
std::shared_ptr<MojangAccountList> m_accounts; std::shared_ptr<MojangAccountList> m_accounts;
std::shared_ptr<LWJGLVersionList> m_lwjgllist;
std::shared_ptr<JavaInstallList> m_javalist; std::shared_ptr<JavaInstallList> m_javalist;
std::shared_ptr<TranslationsModel> m_translations; std::shared_ptr<TranslationsModel> m_translations;
std::shared_ptr<GenericPageProvider> m_globalSettingsProvider; std::shared_ptr<GenericPageProvider> m_globalSettingsProvider;
@ -217,8 +194,10 @@ private:
QString m_rootPath; QString m_rootPath;
Status m_status = MultiMC::StartingUp; Status m_status = MultiMC::StartingUp;
#if defined Q_OS_WIN32
// used on Windows to attach the standard IO streams // used on Windows to attach the standard IO streams
bool consoleAttached = false; bool consoleAttached = false;
#endif
// FIXME: attach to instances instead. // FIXME: attach to instances instead.
struct InstanceXtras struct InstanceXtras