2013-09-07 03:00:58 +01:00
|
|
|
|
|
|
|
#include "MultiMC.h"
|
|
|
|
#include <iostream>
|
|
|
|
#include <QDir>
|
|
|
|
#include <QNetworkAccessManager>
|
2013-09-08 22:43:19 +01:00
|
|
|
#include <QTranslator>
|
|
|
|
#include <QLibraryInfo>
|
2013-10-14 02:59:21 +01:00
|
|
|
#include <QMessageBox>
|
2013-09-07 03:00:58 +01:00
|
|
|
|
|
|
|
#include "gui/mainwindow.h"
|
2013-10-14 02:59:21 +01:00
|
|
|
#include "gui/versionselectdialog.h"
|
2013-09-07 03:00:58 +01:00
|
|
|
#include "logic/lists/InstanceList.h"
|
|
|
|
#include "logic/lists/IconList.h"
|
2013-09-15 23:54:39 +01:00
|
|
|
#include "logic/lists/LwjglVersionList.h"
|
|
|
|
#include "logic/lists/MinecraftVersionList.h"
|
|
|
|
#include "logic/lists/ForgeVersionList.h"
|
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
#include "logic/InstanceLauncher.h"
|
2013-09-08 01:15:20 +01:00
|
|
|
#include "logic/net/HttpMetaCache.h"
|
2013-09-07 03:00:58 +01:00
|
|
|
|
2013-10-06 23:44:34 +01:00
|
|
|
#include "logic/JavaUtils.h"
|
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
#include "pathutils.h"
|
|
|
|
#include "cmdutils.h"
|
|
|
|
#include <inisettingsobject.h>
|
|
|
|
#include <setting.h>
|
2013-10-06 00:13:40 +01:00
|
|
|
#include <logger/QsLog.h>
|
|
|
|
#include <logger/QsLogDest.h>
|
2013-09-07 03:00:58 +01:00
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
using namespace Util::Commandline;
|
|
|
|
|
2013-09-22 23:23:50 +01:00
|
|
|
MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
|
2013-09-07 03:00:58 +01:00
|
|
|
{
|
|
|
|
setOrganizationName("Forkk");
|
|
|
|
setApplicationName("MultiMC 5");
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-09 00:20:17 +01:00
|
|
|
initTranslations();
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// Print app header
|
|
|
|
std::cout << "MultiMC 5" << std::endl;
|
|
|
|
std::cout << "(c) 2013 MultiMC Contributors" << std::endl << std::endl;
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// Commandline parsing
|
|
|
|
QHash<QString, QVariant> args;
|
|
|
|
{
|
|
|
|
Parser parser(FlagStyle::GNU, ArgumentStyle::SpaceAndEquals);
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// --help
|
|
|
|
parser.addSwitch("help");
|
|
|
|
parser.addShortOpt("help", 'h');
|
|
|
|
parser.addDocumentation("help", "display this help and exit.");
|
|
|
|
// --version
|
|
|
|
parser.addSwitch("version");
|
|
|
|
parser.addShortOpt("version", 'V');
|
|
|
|
parser.addDocumentation("version", "display program version and exit.");
|
|
|
|
// --dir
|
|
|
|
parser.addOption("dir", applicationDirPath());
|
|
|
|
parser.addShortOpt("dir", 'd');
|
2013-09-22 23:23:50 +01:00
|
|
|
parser.addDocumentation("dir", "use the supplied directory as MultiMC root instead of "
|
|
|
|
"the binary location (use '.' for current)");
|
2013-09-07 03:00:58 +01:00
|
|
|
// --update
|
|
|
|
parser.addOption("update");
|
|
|
|
parser.addShortOpt("update", 'u');
|
2013-09-22 23:23:50 +01:00
|
|
|
parser.addDocumentation("update", "replaces the given file with the running executable",
|
|
|
|
"<path>");
|
2013-09-07 03:00:58 +01:00
|
|
|
// --quietupdate
|
|
|
|
parser.addSwitch("quietupdate");
|
|
|
|
parser.addShortOpt("quietupdate", 'U');
|
2013-09-22 23:23:50 +01:00
|
|
|
parser.addDocumentation("quietupdate",
|
|
|
|
"doesn't restart MultiMC after installing updates");
|
2013-09-07 03:00:58 +01:00
|
|
|
// --launch
|
|
|
|
parser.addOption("launch");
|
|
|
|
parser.addShortOpt("launch", 'l');
|
|
|
|
parser.addDocumentation("launch", "tries to launch the given instance", "<inst>");
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// parse the arguments
|
|
|
|
try
|
|
|
|
{
|
|
|
|
args = parser.parse(arguments());
|
|
|
|
}
|
2013-09-22 23:23:50 +01:00
|
|
|
catch (ParsingError e)
|
2013-09-07 03:00:58 +01:00
|
|
|
{
|
|
|
|
std::cerr << "CommandLineError: " << e.what() << std::endl;
|
2013-09-22 23:23:50 +01:00
|
|
|
std::cerr << "Try '%1 -h' to get help on MultiMC's command line parameters."
|
|
|
|
<< std::endl;
|
2013-09-07 03:00:58 +01:00
|
|
|
m_status = MultiMC::Failed;
|
|
|
|
return;
|
|
|
|
}
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// display help and exit
|
|
|
|
if (args["help"].toBool())
|
|
|
|
{
|
|
|
|
std::cout << qPrintable(parser.compileHelp(arguments()[0]));
|
|
|
|
m_status = MultiMC::Succeeded;
|
|
|
|
return;
|
|
|
|
}
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// display version and exit
|
|
|
|
if (args["version"].toBool())
|
|
|
|
{
|
|
|
|
std::cout << "Version " << VERSION_STR << std::endl;
|
|
|
|
std::cout << "Git " << GIT_COMMIT << std::endl;
|
2013-09-22 23:23:50 +01:00
|
|
|
std::cout << "Tag: " << JENKINS_BUILD_TAG << " " << (ARCH == x64 ? "x86_64" : "x86")
|
|
|
|
<< std::endl;
|
2013-09-07 03:00:58 +01:00
|
|
|
m_status = MultiMC::Succeeded;
|
|
|
|
return;
|
|
|
|
}
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// update
|
|
|
|
// Note: cwd is always the current executable path!
|
|
|
|
if (!args["update"].isNull())
|
|
|
|
{
|
2013-09-22 23:23:50 +01:00
|
|
|
std::cout << "Performing MultiMC update: " << qPrintable(args["update"].toString())
|
|
|
|
<< std::endl;
|
2013-09-07 03:00:58 +01:00
|
|
|
QString cwd = QDir::currentPath();
|
|
|
|
QDir::setCurrent(applicationDirPath());
|
|
|
|
QFile file(applicationFilePath());
|
|
|
|
file.copy(args["update"].toString());
|
2013-09-22 23:23:50 +01:00
|
|
|
if (args["quietupdate"].toBool())
|
2013-09-07 03:00:58 +01:00
|
|
|
{
|
|
|
|
m_status = MultiMC::Succeeded;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
QDir::setCurrent(cwd);
|
|
|
|
}
|
|
|
|
}
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// change directory
|
|
|
|
QDir::setCurrent(args["dir"].toString());
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-10-06 00:13:40 +01:00
|
|
|
// init the logger
|
|
|
|
initLogger();
|
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// load settings
|
|
|
|
initGlobalSettings();
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// and instances
|
2013-09-22 23:23:50 +01:00
|
|
|
m_instances.reset(new InstanceList(m_settings->get("InstanceDir").toString(), this));
|
2013-10-06 02:07:57 +01:00
|
|
|
QLOG_INFO() << "Loading Instances...";
|
2013-09-07 03:00:58 +01:00
|
|
|
m_instances->loadList();
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-08 01:15:20 +01:00
|
|
|
// init the http meta cache
|
|
|
|
initHttpMetaCache();
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-08 01:15:20 +01:00
|
|
|
// create the global network manager
|
2013-09-22 03:21:36 +01:00
|
|
|
m_qnam.reset(new QNetworkAccessManager(this));
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// Register meta types.
|
|
|
|
qRegisterMetaType<LoginResponse>("LoginResponse");
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// launch instance, if that's what should be done
|
|
|
|
if (!args["launch"].isNull())
|
|
|
|
{
|
2013-09-22 23:23:50 +01:00
|
|
|
if (InstanceLauncher(args["launch"].toString()).launch())
|
2013-09-07 03:00:58 +01:00
|
|
|
m_status = MultiMC::Succeeded;
|
|
|
|
else
|
|
|
|
m_status = MultiMC::Failed;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_status = MultiMC::Initialized;
|
|
|
|
}
|
|
|
|
|
|
|
|
MultiMC::~MultiMC()
|
|
|
|
{
|
2013-09-22 23:23:50 +01:00
|
|
|
if (m_mmc_translator)
|
2013-09-09 00:20:17 +01:00
|
|
|
{
|
2013-10-06 00:13:40 +01:00
|
|
|
removeTranslator(m_mmc_translator.get());
|
2013-09-09 00:20:17 +01:00
|
|
|
}
|
2013-09-22 23:23:50 +01:00
|
|
|
if (m_qt_translator)
|
2013-09-09 00:20:17 +01:00
|
|
|
{
|
2013-10-06 00:13:40 +01:00
|
|
|
removeTranslator(m_qt_translator.get());
|
2013-09-09 00:20:17 +01:00
|
|
|
}
|
2013-09-07 03:00:58 +01:00
|
|
|
}
|
|
|
|
|
2013-09-09 00:20:17 +01:00
|
|
|
void MultiMC::initTranslations()
|
|
|
|
{
|
2013-09-22 03:21:36 +01:00
|
|
|
m_qt_translator.reset(new QTranslator());
|
2013-09-22 23:23:50 +01:00
|
|
|
if (m_qt_translator->load("qt_" + QLocale::system().name(),
|
|
|
|
QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
|
2013-09-09 00:20:17 +01:00
|
|
|
{
|
2013-09-22 23:23:50 +01:00
|
|
|
std::cout << "Loading Qt Language File for "
|
|
|
|
<< QLocale::system().name().toLocal8Bit().constData() << "...";
|
2013-10-06 00:13:40 +01:00
|
|
|
if (!installTranslator(m_qt_translator.get()))
|
2013-09-09 00:20:17 +01:00
|
|
|
{
|
|
|
|
std::cout << " failed.";
|
2013-09-22 03:21:36 +01:00
|
|
|
m_qt_translator.reset();
|
2013-09-09 00:20:17 +01:00
|
|
|
}
|
|
|
|
std::cout << std::endl;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-09-22 03:21:36 +01:00
|
|
|
m_qt_translator.reset();
|
2013-09-09 00:20:17 +01:00
|
|
|
}
|
|
|
|
|
2013-09-22 03:21:36 +01:00
|
|
|
m_mmc_translator.reset(new QTranslator());
|
2013-09-22 23:23:50 +01:00
|
|
|
if (m_mmc_translator->load("mmc_" + QLocale::system().name(),
|
|
|
|
QDir("translations").absolutePath()))
|
2013-09-09 00:20:17 +01:00
|
|
|
{
|
2013-09-22 23:23:50 +01:00
|
|
|
std::cout << "Loading MMC Language File for "
|
|
|
|
<< QLocale::system().name().toLocal8Bit().constData() << "...";
|
2013-10-06 00:13:40 +01:00
|
|
|
if (!installTranslator(m_mmc_translator.get()))
|
2013-09-09 00:20:17 +01:00
|
|
|
{
|
|
|
|
std::cout << " failed.";
|
2013-09-22 03:21:36 +01:00
|
|
|
m_mmc_translator.reset();
|
2013-09-09 00:20:17 +01:00
|
|
|
}
|
|
|
|
std::cout << std::endl;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-09-22 03:21:36 +01:00
|
|
|
m_mmc_translator.reset();
|
2013-09-09 00:20:17 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-06 00:13:40 +01:00
|
|
|
void MultiMC::initLogger()
|
|
|
|
{
|
|
|
|
// init the logging mechanism
|
|
|
|
QsLogging::Logger &logger = QsLogging::Logger::instance();
|
|
|
|
logger.setLoggingLevel(QsLogging::TraceLevel);
|
|
|
|
m_fileDestination = QsLogging::DestinationFactory::MakeFileDestination("MultiMC.log");
|
|
|
|
m_debugDestination = QsLogging::DestinationFactory::MakeDebugOutputDestination();
|
|
|
|
logger.addDestination(m_fileDestination.get());
|
|
|
|
logger.addDestination(m_debugDestination.get());
|
|
|
|
// log all the things
|
|
|
|
logger.setLoggingLevel(QsLogging::TraceLevel);
|
|
|
|
}
|
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
void MultiMC::initGlobalSettings()
|
|
|
|
{
|
2013-09-22 03:21:36 +01:00
|
|
|
m_settings.reset(new INISettingsObject("multimc.cfg", this));
|
2013-09-22 23:23:50 +01:00
|
|
|
// Updates
|
2013-09-07 03:00:58 +01:00
|
|
|
m_settings->registerSetting(new Setting("UseDevBuilds", false));
|
|
|
|
m_settings->registerSetting(new Setting("AutoUpdate", true));
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// Folders
|
|
|
|
m_settings->registerSetting(new Setting("InstanceDir", "instances"));
|
|
|
|
m_settings->registerSetting(new Setting("CentralModsDir", "mods"));
|
|
|
|
m_settings->registerSetting(new Setting("LWJGLDir", "lwjgl"));
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// Console
|
|
|
|
m_settings->registerSetting(new Setting("ShowConsole", true));
|
|
|
|
m_settings->registerSetting(new Setting("AutoCloseConsole", true));
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// Toolbar settings
|
|
|
|
m_settings->registerSetting(new Setting("InstanceToolbarVisible", true));
|
|
|
|
m_settings->registerSetting(new Setting("InstanceToolbarPosition", QPoint()));
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// Console Colors
|
2013-09-22 23:23:50 +01:00
|
|
|
// m_settings->registerSetting(new Setting("SysMessageColor", QColor(Qt::blue)));
|
|
|
|
// m_settings->registerSetting(new Setting("StdOutColor", QColor(Qt::black)));
|
|
|
|
// m_settings->registerSetting(new Setting("StdErrColor", QColor(Qt::red)));
|
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// Window Size
|
|
|
|
m_settings->registerSetting(new Setting("LaunchMaximized", false));
|
|
|
|
m_settings->registerSetting(new Setting("MinecraftWinWidth", 854));
|
|
|
|
m_settings->registerSetting(new Setting("MinecraftWinHeight", 480));
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// Auto login
|
|
|
|
m_settings->registerSetting(new Setting("AutoLogin", false));
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// Memory
|
|
|
|
m_settings->registerSetting(new Setting("MinMemAlloc", 512));
|
|
|
|
m_settings->registerSetting(new Setting("MaxMemAlloc", 1024));
|
|
|
|
m_settings->registerSetting(new Setting("PermGen", 64));
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// Java Settings
|
2013-10-06 23:44:34 +01:00
|
|
|
m_settings->registerSetting(new Setting("JavaPath", ""));
|
2013-09-07 03:00:58 +01:00
|
|
|
m_settings->registerSetting(new Setting("JvmArgs", ""));
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// Custom Commands
|
|
|
|
m_settings->registerSetting(new Setting("PreLaunchCommand", ""));
|
|
|
|
m_settings->registerSetting(new Setting("PostExitCommand", ""));
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// The cat
|
|
|
|
m_settings->registerSetting(new Setting("TheCat", false));
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-08 15:21:49 +01:00
|
|
|
// Shall the main window hide on instance launch
|
|
|
|
m_settings->registerSetting(new Setting("NoHide", false));
|
2013-09-22 23:23:50 +01:00
|
|
|
|
|
|
|
// Persistent value for the client ID
|
|
|
|
m_settings->registerSetting(new Setting("YggdrasilClientToken", ""));
|
|
|
|
QString currentYggID = m_settings->get("YggdrasilClientToken").toString();
|
|
|
|
if (currentYggID.isEmpty())
|
|
|
|
{
|
|
|
|
QUuid uuid = QUuid::createUuid();
|
|
|
|
m_settings->set("YggdrasilClientToken", uuid.toString());
|
|
|
|
}
|
2013-09-07 03:00:58 +01:00
|
|
|
}
|
|
|
|
|
2013-09-08 01:15:20 +01:00
|
|
|
void MultiMC::initHttpMetaCache()
|
|
|
|
{
|
2013-09-22 03:21:36 +01:00
|
|
|
m_metacache.reset(new HttpMetaCache("metacache"));
|
2013-09-08 01:15:20 +01:00
|
|
|
m_metacache->addBase("assets", QDir("assets").absolutePath());
|
|
|
|
m_metacache->addBase("versions", QDir("versions").absolutePath());
|
|
|
|
m_metacache->addBase("libraries", QDir("libraries").absolutePath());
|
2013-09-17 23:00:35 +01:00
|
|
|
m_metacache->addBase("minecraftforge", QDir("mods/minecraftforge").absolutePath());
|
2013-09-08 01:15:20 +01:00
|
|
|
m_metacache->Load();
|
|
|
|
}
|
|
|
|
|
2013-10-06 00:13:40 +01:00
|
|
|
std::shared_ptr<IconList> MultiMC::icons()
|
2013-09-07 03:00:58 +01:00
|
|
|
{
|
2013-09-22 23:23:50 +01:00
|
|
|
if (!m_icons)
|
2013-09-07 03:00:58 +01:00
|
|
|
{
|
2013-09-22 03:21:36 +01:00
|
|
|
m_icons.reset(new IconList);
|
2013-09-07 03:00:58 +01:00
|
|
|
}
|
|
|
|
return m_icons;
|
|
|
|
}
|
|
|
|
|
2013-10-06 00:13:40 +01:00
|
|
|
std::shared_ptr<LWJGLVersionList> MultiMC::lwjgllist()
|
2013-09-15 23:54:39 +01:00
|
|
|
{
|
2013-09-22 23:23:50 +01:00
|
|
|
if (!m_lwjgllist)
|
2013-09-15 23:54:39 +01:00
|
|
|
{
|
2013-09-22 03:21:36 +01:00
|
|
|
m_lwjgllist.reset(new LWJGLVersionList());
|
2013-09-15 23:54:39 +01:00
|
|
|
}
|
|
|
|
return m_lwjgllist;
|
|
|
|
}
|
2013-09-22 03:21:36 +01:00
|
|
|
|
2013-10-06 00:13:40 +01:00
|
|
|
std::shared_ptr<ForgeVersionList> MultiMC::forgelist()
|
2013-09-15 23:54:39 +01:00
|
|
|
{
|
2013-09-22 23:23:50 +01:00
|
|
|
if (!m_forgelist)
|
2013-09-15 23:54:39 +01:00
|
|
|
{
|
2013-09-22 03:21:36 +01:00
|
|
|
m_forgelist.reset(new ForgeVersionList());
|
2013-09-15 23:54:39 +01:00
|
|
|
}
|
|
|
|
return m_forgelist;
|
|
|
|
}
|
|
|
|
|
2013-10-06 00:13:40 +01:00
|
|
|
std::shared_ptr<MinecraftVersionList> MultiMC::minecraftlist()
|
2013-09-15 23:54:39 +01:00
|
|
|
{
|
2013-09-22 23:23:50 +01:00
|
|
|
if (!m_minecraftlist)
|
2013-09-15 23:54:39 +01:00
|
|
|
{
|
2013-09-22 03:21:36 +01:00
|
|
|
m_minecraftlist.reset(new MinecraftVersionList());
|
2013-09-15 23:54:39 +01:00
|
|
|
}
|
|
|
|
return m_minecraftlist;
|
|
|
|
}
|
|
|
|
|
2013-10-14 02:59:21 +01:00
|
|
|
std::shared_ptr<JavaVersionList> MultiMC::javalist()
|
|
|
|
{
|
|
|
|
if (!m_javalist)
|
|
|
|
{
|
|
|
|
m_javalist.reset(new JavaVersionList());
|
|
|
|
}
|
|
|
|
return m_javalist;
|
|
|
|
}
|
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
// initialize Qt
|
|
|
|
MultiMC app(argc, argv);
|
2013-09-22 23:23:50 +01:00
|
|
|
|
2013-09-07 03:00:58 +01:00
|
|
|
// show main window
|
|
|
|
MainWindow mainWin;
|
|
|
|
mainWin.show();
|
2013-10-14 02:59:21 +01:00
|
|
|
mainWin.checkSetDefaultJava();
|
2013-09-22 23:23:50 +01:00
|
|
|
|
|
|
|
switch (app.status())
|
2013-09-07 03:00:58 +01:00
|
|
|
{
|
2013-09-22 23:23:50 +01:00
|
|
|
case MultiMC::Initialized:
|
|
|
|
return app.exec();
|
|
|
|
case MultiMC::Failed:
|
|
|
|
return 1;
|
|
|
|
case MultiMC::Succeeded:
|
|
|
|
return 0;
|
2013-09-07 03:00:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-22 03:21:36 +01:00
|
|
|
#include "MultiMC.moc"
|