summaryrefslogtreecommitdiffstats
path: root/libmultimc/src
diff options
context:
space:
mode:
Diffstat (limited to 'libmultimc/src')
-rw-r--r--libmultimc/src/appsettings.cpp68
-rw-r--r--libmultimc/src/gameupdatetask.cpp22
-rw-r--r--libmultimc/src/instance.cpp131
-rw-r--r--libmultimc/src/instancelist.cpp87
-rw-r--r--libmultimc/src/instanceloader.cpp109
-rw-r--r--libmultimc/src/instversion.cpp32
-rw-r--r--libmultimc/src/instversionlist.cpp21
-rw-r--r--libmultimc/src/loginresponse.cpp69
-rw-r--r--libmultimc/src/logintask.cpp121
-rw-r--r--libmultimc/src/minecraftprocess.cpp248
-rw-r--r--libmultimc/src/pluginmanager.cpp105
-rw-r--r--libmultimc/src/task.cpp56
-rw-r--r--libmultimc/src/userinfo.cpp49
-rw-r--r--libmultimc/src/version.cpp46
14 files changed, 1164 insertions, 0 deletions
diff --git a/libmultimc/src/appsettings.cpp b/libmultimc/src/appsettings.cpp
new file mode 100644
index 00000000..68d2c015
--- /dev/null
+++ b/libmultimc/src/appsettings.cpp
@@ -0,0 +1,68 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "appsettings.h"
+
+#include <setting.h>
+
+#include <QPoint>
+//#include <QColor>
+
+AppSettings::AppSettings(QObject *parent) :
+ BasicSettingsObject(parent)
+{
+ // Updates
+ registerSetting(new Setting("UseDevBuilds", false));
+ registerSetting(new Setting("AutoUpdate", true));
+
+ // Folders
+ registerSetting(new Setting("InstanceDir", "instances"));
+ registerSetting(new Setting("CentralModsDir", "mods"));
+ registerSetting(new Setting("LWJGLDir", "lwjgl"));
+
+ // Console
+ registerSetting(new Setting("ShowConsole", true));
+ registerSetting(new Setting("AutoCloseConsole", true));
+
+ // Toolbar settings
+ registerSetting(new Setting("InstanceToolbarVisible", true));
+ registerSetting(new Setting("InstanceToolbarPosition", QPoint()));
+
+ // Console Colors
+// registerSetting(new Setting("SysMessageColor", QColor(Qt::blue)));
+// registerSetting(new Setting("StdOutColor", QColor(Qt::black)));
+// registerSetting(new Setting("StdErrColor", QColor(Qt::red)));
+
+ // Window Size
+ registerSetting(new Setting("LaunchCompatMode", false));
+ registerSetting(new Setting("LaunchMaximized", false));
+ registerSetting(new Setting("MinecraftWinWidth", 854));
+ registerSetting(new Setting("MinecraftWinHeight", 480));
+
+ // Auto login
+ registerSetting(new Setting("AutoLogin", false));
+
+ // Memory
+ registerSetting(new Setting("MinMemAlloc", 512));
+ registerSetting(new Setting("MaxMemAlloc", 1024));
+
+ // Java Settings
+ registerSetting(new Setting("JavaPath", "java"));
+ registerSetting(new Setting("JvmArgs", ""));
+
+ // Custom Commands
+ registerSetting(new Setting("PreLaunchCommand", ""));
+ registerSetting(new Setting("PostExitCommand", ""));
+}
diff --git a/libmultimc/src/gameupdatetask.cpp b/libmultimc/src/gameupdatetask.cpp
new file mode 100644
index 00000000..c152147e
--- /dev/null
+++ b/libmultimc/src/gameupdatetask.cpp
@@ -0,0 +1,22 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "gameupdatetask.h"
+
+GameUpdateTask::GameUpdateTask(const LoginResponse &response, QObject *parent) :
+ QObject(parent), m_response(response)
+{
+
+}
diff --git a/libmultimc/src/instance.cpp b/libmultimc/src/instance.cpp
new file mode 100644
index 00000000..377acd32
--- /dev/null
+++ b/libmultimc/src/instance.cpp
@@ -0,0 +1,131 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "include/instance.h"
+
+#include <QFileInfo>
+
+#include "inisettingsobject.h"
+#include "setting.h"
+#include "overridesetting.h"
+
+#include "pathutils.h"
+
+Instance::Instance(const QString &rootDir, QObject *parent) :
+ QObject(parent)
+{
+ m_rootDir = rootDir;
+ m_settings = new INISettingsObject(PathCombine(rootDir, "instance.cfg"), this);
+
+ settings().registerSetting(new Setting("name", "Unnamed Instance"));
+ settings().registerSetting(new Setting("iconKey", "default"));
+ settings().registerSetting(new Setting("notes", ""));
+ settings().registerSetting(new Setting("NeedsRebuild", true));
+ settings().registerSetting(new Setting("JarVersion", "Unknown"));
+ settings().registerSetting(new Setting("LwjglVersion", "Mojang"));
+ settings().registerSetting(new Setting("IntendedJarVersion", ""));
+ settings().registerSetting(new Setting("lastLaunchTime", 0));
+
+ // Java Settings
+ settings().registerSetting(new OverrideSetting("JavaPath", globalSettings->getSetting("JavaPath")));
+ settings().registerSetting(new OverrideSetting("JvmArgs", globalSettings->getSetting("JvmArgs")));
+
+ // Custom Commands
+ settings().registerSetting(new OverrideSetting("PreLaunchCommand",
+ globalSettings->getSetting("PreLaunchCommand")));
+ settings().registerSetting(new OverrideSetting("PostExitCommand",
+ globalSettings->getSetting("PostExitCommand")));
+
+ // Memory
+ settings().registerSetting(new OverrideSetting("MinMemAlloc", globalSettings->getSetting("MinMemAlloc")));
+ settings().registerSetting(new OverrideSetting("MaxMemAlloc", globalSettings->getSetting("MaxMemAlloc")));
+
+ // Auto login
+ settings().registerSetting(new OverrideSetting("AutoLogin", globalSettings->getSetting("AutoLogin")));
+}
+
+QString Instance::id() const
+{
+ return QFileInfo(rootDir()).fileName();
+}
+
+QString Instance::rootDir() const
+{
+ return m_rootDir;
+}
+
+InstanceList *Instance::instList() const
+{
+ if (parent()->inherits("InstanceList"))
+ return (InstanceList *)parent();
+ else
+ return NULL;
+}
+
+QString Instance::minecraftDir() const
+{
+ QFileInfo mcDir(PathCombine(rootDir(), "minecraft"));
+ QFileInfo dotMCDir(PathCombine(rootDir(), ".minecraft"));
+
+ if (dotMCDir.exists() && !mcDir.exists())
+ return dotMCDir.filePath();
+ else
+ return mcDir.filePath();
+}
+
+QString Instance::binDir() const
+{
+ return PathCombine(minecraftDir(), "bin");
+}
+
+QString Instance::savesDir() const
+{
+ return PathCombine(minecraftDir(), "saves");
+}
+
+QString Instance::mlModsDir() const
+{
+ return PathCombine(minecraftDir(), "mods");
+}
+
+QString Instance::coreModsDir() const
+{
+ return PathCombine(minecraftDir(), "coremods");
+}
+
+QString Instance::resourceDir() const
+{
+ return PathCombine(minecraftDir(), "resources");
+}
+
+QString Instance::screenshotsDir() const
+{
+ return PathCombine(minecraftDir(), "screenshots");
+}
+
+QString Instance::texturePacksDir() const
+{
+ return PathCombine(minecraftDir(), "texturepacks");
+}
+
+QString Instance::mcJar() const
+{
+ return PathCombine(binDir(), "minecraft.jar");
+}
+
+SettingsObject &Instance::settings() const
+{
+ return *m_settings;
+}
diff --git a/libmultimc/src/instancelist.cpp b/libmultimc/src/instancelist.cpp
new file mode 100644
index 00000000..3b0b668f
--- /dev/null
+++ b/libmultimc/src/instancelist.cpp
@@ -0,0 +1,87 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "include/instancelist.h"
+
+#include "siglist_impl.h"
+
+#include <QDir>
+#include <QFile>
+#include <QDirIterator>
+
+#include "include/instance.h"
+#include "include/instanceloader.h"
+
+#include "pathutils.h"
+
+
+InstanceList::InstanceList(const QString &instDir, QObject *parent) :
+ QObject(parent), m_instDir(instDir)
+{
+
+}
+
+InstanceList::InstListError InstanceList::loadList()
+{
+ QDir dir(m_instDir);
+ QDirIterator iter(dir);
+
+ while (iter.hasNext())
+ {
+ QString subDir = iter.next();
+ if (QFileInfo(PathCombine(subDir, "instance.cfg")).exists())
+ {
+ Instance *instPtr = NULL;
+
+ InstanceLoader::InstTypeError error = InstanceLoader::get().
+ loadInstance(instPtr, subDir);
+
+ if (error != InstanceLoader::NoError &&
+ error != InstanceLoader::NotAnInstance)
+ {
+ QString errorMsg = QString("Failed to load instance %1: ").
+ arg(QFileInfo(subDir).baseName()).toUtf8();
+
+ switch (error)
+ {
+ case InstanceLoader::TypeNotRegistered:
+ errorMsg += "Instance type not found.";
+ break;
+
+ default:
+ errorMsg += QString("Unknown instance loader error %1").
+ arg(error);
+ break;
+ }
+ qDebug(errorMsg.toUtf8());
+ }
+ else if (!instPtr)
+ {
+ qDebug(QString("Error loading instance %1. Instance loader returned null.").
+ arg(QFileInfo(subDir).baseName()).toUtf8());
+ }
+ else
+ {
+ QSharedPointer<Instance> inst(instPtr);
+
+ qDebug(QString("Loaded instance %1").arg(inst->name()).toUtf8());
+ inst->setParent(this);
+ append(QSharedPointer<Instance>(inst));
+ }
+ }
+ }
+
+ return NoError;
+}
diff --git a/libmultimc/src/instanceloader.cpp b/libmultimc/src/instanceloader.cpp
new file mode 100644
index 00000000..9d98230f
--- /dev/null
+++ b/libmultimc/src/instanceloader.cpp
@@ -0,0 +1,109 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "include/instanceloader.h"
+
+#include <QFileInfo>
+
+#include "include/instancetypeinterface.h"
+
+#include "inifile.h"
+
+#include "pathutils.h"
+
+InstanceLoader InstanceLoader::loader;
+
+InstanceLoader::InstanceLoader() :
+ QObject(NULL)
+{
+
+}
+
+
+InstanceLoader::InstTypeError InstanceLoader::registerInstanceType(InstanceTypeInterface *type)
+{
+ // Check to see if the type ID exists.
+ if (m_typeMap.contains(type->typeID()))
+ return TypeIDExists;
+
+ // Set the parent to this.
+ // ((QObject *)type)->setParent(this);
+
+ // Add it to the map.
+ m_typeMap.insert(type->typeID(), type);
+
+ qDebug(QString("Registered instance type %1.").
+ arg(type->typeID()).toUtf8());
+ return NoError;
+}
+
+InstanceLoader::InstTypeError InstanceLoader::createInstance(Instance *&inst,
+ const InstanceTypeInterface *type,
+ const QString &instDir)
+{
+ // Check if the type is registered.
+ if (!type || findType(type->typeID()) != type)
+ return TypeNotRegistered;
+
+ // Create the instance.
+ return type->createInstance(inst, instDir);
+}
+
+InstanceLoader::InstTypeError InstanceLoader::loadInstance(Instance *&inst,
+ const InstanceTypeInterface *type,
+ const QString &instDir)
+{
+ // Check if the type is registered.
+ if (!type || findType(type->typeID()) != type)
+ return TypeNotRegistered;
+
+ return type->loadInstance(inst, instDir);
+}
+
+InstanceLoader::InstTypeError InstanceLoader::loadInstance(Instance *&inst,
+ const QString &instDir)
+{
+ QFileInfo instConfig(PathCombine(instDir, "instance.cfg"));
+
+ if (!instConfig.exists())
+ return NotAnInstance;
+
+ INIFile ini;
+ ini.loadFile(instConfig.path());
+ QString typeName = ini.get("type", "net.forkk.MultiMC.StdInstance").toString();
+ const InstanceTypeInterface *type = findType(typeName);
+
+ return loadInstance(inst, type, instDir);
+}
+
+const InstanceTypeInterface *InstanceLoader::findType(const QString &id)
+{
+ if (!m_typeMap.contains(id))
+ return NULL;
+ else
+ return m_typeMap[id];
+}
+
+InstTypeList InstanceLoader::typeList()
+{
+ InstTypeList typeList;
+
+ for (QMap<QString, InstanceTypeInterface *>::iterator iter = m_typeMap.begin(); iter != m_typeMap.end(); iter++)
+ {
+ typeList.append(*iter);
+ }
+
+ return typeList;
+}
diff --git a/libmultimc/src/instversion.cpp b/libmultimc/src/instversion.cpp
new file mode 100644
index 00000000..cedb61df
--- /dev/null
+++ b/libmultimc/src/instversion.cpp
@@ -0,0 +1,32 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "include/instversion.h"
+#include "include/instversionlist.h"
+
+InstVersion::InstVersion(InstVersionList *parent) :
+ QObject(parent)
+{
+
+}
+
+InstVersionList *InstVersion::versionList() const
+{
+ // Parent should *always* be an InstVersionList
+ if (!parent() || !parent()->inherits("InstVersionList"))
+ return NULL;
+ else
+ return (InstVersionList *)parent();
+}
diff --git a/libmultimc/src/instversionlist.cpp b/libmultimc/src/instversionlist.cpp
new file mode 100644
index 00000000..e171cfa5
--- /dev/null
+++ b/libmultimc/src/instversionlist.cpp
@@ -0,0 +1,21 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "include/instversionlist.h"
+
+InstVersionList::InstVersionList() :
+ QObject(NULL)
+{
+}
diff --git a/libmultimc/src/loginresponse.cpp b/libmultimc/src/loginresponse.cpp
new file mode 100644
index 00000000..99a618ad
--- /dev/null
+++ b/libmultimc/src/loginresponse.cpp
@@ -0,0 +1,69 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "loginresponse.h"
+
+LoginResponse::LoginResponse(const QString& username, const QString& sessionID,
+ qint64 latestVersion, QObject *parent) :
+ QObject(parent)
+{
+ this->m_username = username;
+ this->m_sessionID = sessionID;
+ this->m_latestVersion = latestVersion;
+}
+
+LoginResponse::LoginResponse()
+{
+ this->m_username = "";
+ this->m_sessionID = "";
+ this->m_latestVersion = 0;
+}
+
+LoginResponse::LoginResponse(const LoginResponse &other)
+{
+ this->m_username = other.username();
+ this->m_sessionID = other.sessionID();
+ this->m_latestVersion = other.latestVersion();
+}
+
+QString LoginResponse::username() const
+{
+ return m_username;
+}
+
+void LoginResponse::setUsername(const QString& username)
+{
+ this->m_username = username;
+}
+
+QString LoginResponse::sessionID() const
+{
+ return m_sessionID;
+}
+
+void LoginResponse::setSessionID(const QString& sessionID)
+{
+ this->m_sessionID = sessionID;
+}
+
+qint64 LoginResponse::latestVersion() const
+{
+ return m_latestVersion;
+}
+
+void LoginResponse::setLatestVersion(qint64 v)
+{
+ this->m_latestVersion = v;
+}
diff --git a/libmultimc/src/logintask.cpp b/libmultimc/src/logintask.cpp
new file mode 100644
index 00000000..71075630
--- /dev/null
+++ b/libmultimc/src/logintask.cpp
@@ -0,0 +1,121 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "logintask.h"
+
+#include <QStringList>
+
+#include <QtNetwork/QNetworkAccessManager>
+#include <QtNetwork/QNetworkReply>
+#include <QtNetwork/QNetworkRequest>
+
+#include <QUrl>
+#include <QUrlQuery>
+
+LoginTask::LoginTask(const UserInfo &uInfo, QObject *parent) :
+ Task(parent), uInfo(uInfo)
+{
+
+}
+
+void LoginTask::executeTask()
+{
+ setStatus("Logging in...");
+
+ QNetworkAccessManager netMgr;
+ connect(&netMgr, SIGNAL(finished(QNetworkReply*)),
+ SLOT(processNetReply(QNetworkReply*)));
+
+ QUrl loginURL("https://login.minecraft.net/");
+ QNetworkRequest netRequest(loginURL);
+ netRequest.setHeader(QNetworkRequest::ContentTypeHeader,
+ "application/x-www-form-urlencoded");
+
+ QUrlQuery params;
+ params.addQueryItem("user", uInfo.username());
+ params.addQueryItem("password", uInfo.password());
+ params.addQueryItem("version", "13");
+
+ netReply = netMgr.post(netRequest, params.query(QUrl::EncodeSpaces).toUtf8());
+ exec();
+}
+
+void LoginTask::processNetReply(QNetworkReply *reply)
+{
+ // Check for errors.
+ switch (reply->error())
+ {
+ case QNetworkReply::NoError:
+ {
+ // Check the response code.
+ int responseCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+
+ if (responseCode == 200)
+ {
+ QString responseStr(reply->readAll());
+
+ QStringList strings = responseStr.split(":");
+ if (strings.count() >= 4)
+ {
+ bool parseSuccess;
+ qint64 latestVersion = strings[0].toLongLong(&parseSuccess);
+ if (parseSuccess)
+ {
+ // strings[1] is the download ticket. It isn't used anymore.
+ QString username = strings[2];
+ QString sessionID = strings[3];
+
+ LoginResponse response(username, sessionID, latestVersion);
+ emit loginComplete(response);
+ }
+ else
+ {
+ emit loginFailed("Failed to parse Minecraft version string.");
+ }
+ }
+ else
+ {
+ if (responseStr.toLower() == "bad login")
+ emit loginFailed("Invalid username or password.");
+ else if (responseStr.toLower() == "old version")
+ emit loginFailed("Launcher outdated, please update.");
+ else
+ emit loginFailed("Login failed: " + responseStr);
+ }
+ }
+ else if (responseCode == 503)
+ {
+ emit loginFailed("The login servers are currently unavailable. "
+ "Check http://help.mojang.com/ for more info.");
+ }
+ else
+ {
+ emit loginFailed(QString("Login failed: Unknown HTTP error %1 occurred.").
+ arg(QString::number(responseCode)));
+ }
+ break;
+ }
+
+ case QNetworkReply::OperationCanceledError:
+ emit loginFailed("Login canceled.");
+ break;
+
+ default:
+ emit loginFailed("Login failed: " + reply->errorString());
+ break;
+ }
+
+ quit();
+}
diff --git a/libmultimc/src/minecraftprocess.cpp b/libmultimc/src/minecraftprocess.cpp
new file mode 100644
index 00000000..943d76b1
--- /dev/null
+++ b/libmultimc/src/minecraftprocess.cpp
@@ -0,0 +1,248 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Authors: Orochimarufan <orochimarufan.x3@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "minecraftprocess.h"
+
+#include <QDataStream>
+#include <QFile>
+#include <QDir>
+//#include <QImage>
+#include <QProcessEnvironment>
+
+#include "instance.h"
+
+#include "osutils.h"
+#include "pathutils.h"
+
+#define LAUNCHER_FILE "MultiMCLauncher.jar"
+#define IBUS "@im=ibus"
+
+// commandline splitter
+QStringList MinecraftProcess::splitArgs(QString args)
+{
+ QStringList argv;
+ QString current;
+ bool escape = false;
+ QChar inquotes;
+ for (int i=0; i<args.length(); i++)
+ {
+ QChar cchar = args.at(i);
+
+ // \ escaped
+ if (escape) {
+ current += cchar;
+ escape = false;
+ // in "quotes"
+ } else if (!inquotes.isNull()) {
+ if (cchar == 0x5C)
+ escape = true;
+ else if (cchar == inquotes)
+ inquotes = 0;
+ else
+ current += cchar;
+ // otherwise
+ } else {
+ if (cchar == 0x20) {
+ if (!current.isEmpty()) {
+ argv << current;
+ current.clear();
+ }
+ } else if (cchar == 0x22 || cchar == 0x27)
+ inquotes = cchar;
+ else
+ current += cchar;
+ }
+ }
+ if (!current.isEmpty())
+ argv << current;
+ return argv;
+}
+
+// prepare tools
+inline void MinecraftProcess::extractIcon(InstancePtr inst, QString destination)
+{
+// QImage(":/icons/instances/" + inst->iconKey()).save(destination);
+}
+
+inline void MinecraftProcess::extractLauncher(QString destination)
+{
+ QFile(":/launcher/launcher.jar").copy(destination);
+}
+
+void MinecraftProcess::prepare(InstancePtr inst)
+{
+ extractLauncher(PathCombine(inst->minecraftDir(), LAUNCHER_FILE));
+ extractIcon(inst, PathCombine(inst->minecraftDir(), "icon.png"));
+}
+
+// constructor
+MinecraftProcess::MinecraftProcess(InstancePtr inst, QString user, QString session) :
+ m_instance(inst), m_user(user), m_session(session)
+{
+ connect(this, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(finish(int, QProcess::ExitStatus)));
+
+ // prepare the process environment
+ QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+
+#ifdef LINUX
+ // Strip IBus
+ if (env.value("XMODIFIERS").contains(IBUS))
+ env.insert("XMODIFIERS", env.value("XMODIFIERS").replace(IBUS, ""));
+#endif
+
+ // export some infos
+ env.insert("INST_NAME", inst->name());
+ env.insert("INST_ID", inst->id());
+ env.insert("INST_DIR", QDir(inst->rootDir()).absolutePath());
+
+ this->setProcessEnvironment(env);
+ m_prepostlaunchprocess.setProcessEnvironment(env);
+
+ // set the cwd
+ QDir mcDir(inst->minecraftDir());
+ this->setWorkingDirectory(mcDir.absolutePath());
+ m_prepostlaunchprocess.setWorkingDirectory(mcDir.absolutePath());
+
+ // std channels
+ connect(this, SIGNAL(readyReadStandardError()), SLOT(on_stdErr()));
+ connect(this, SIGNAL(readyReadStandardOutput()), SLOT(on_stdOut()));
+}
+
+// console window
+void MinecraftProcess::on_stdErr()
+{
+// if (m_console != nullptr)
+// m_console->write(readAllStandardError(), ConsoleWindow::ERROR);
+}
+
+void MinecraftProcess::on_stdOut()
+{
+// if (m_console != nullptr)
+// m_console->write(readAllStandardOutput(), ConsoleWindow::DEFAULT);
+}
+
+void MinecraftProcess::log(QString text)
+{
+// if (m_console != nullptr)
+// m_console->write(text);
+// else
+ qDebug(qPrintable(text));
+}
+
+// exit handler
+void MinecraftProcess::finish(int code, ExitStatus status)
+{
+ if (status != NormalExit)
+ {
+ //TODO: error handling
+ }
+
+ log("Minecraft exited.");
+
+ m_prepostlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(code));
+
+ // run post-exit
+ if (!m_instance->settings().get("PostExitCommand").toString().isEmpty())
+ {
+ m_prepostlaunchprocess.start(m_instance->settings().get("PostExitCommand").toString());
+ m_prepostlaunchprocess.waitForFinished();
+ if (m_prepostlaunchprocess.exitStatus() != NormalExit)
+ {
+ //TODO: error handling
+ }
+ }
+
+// if (m_console != nullptr)
+// m_console->setMayClose(true);
+
+ emit ended();
+}
+
+void MinecraftProcess::launch()
+{
+ if (!m_instance->settings().get("PreLaunchCommand").toString().isEmpty())
+ {
+ m_prepostlaunchprocess.start(m_instance->settings().get("PreLaunchCommand").toString());
+ m_prepostlaunchprocess.waitForFinished();
+ if (m_prepostlaunchprocess.exitStatus() != NormalExit)
+ {
+ //TODO: error handling
+ return;
+ }
+ }
+
+ m_instance->setLastLaunch();
+
+ prepare(m_instance);
+
+ genArgs();
+
+ log(QString("Minecraft folder is: '%1'").arg(workingDirectory()));
+ log(QString("Instance launched with arguments: '%1'").arg(m_arguments.join("' '")));
+
+ start(m_instance->settings().get("JavaPath").toString(), m_arguments);
+ if (!waitForStarted())
+ {
+ //TODO: error handling
+ }
+
+// if(m_console != nullptr)
+// m_console->setMayClose(false);
+}
+
+void MinecraftProcess::genArgs()
+{
+ // start fresh
+ m_arguments.clear();
+
+ // window size
+ QString windowSize;
+ if (m_instance->settings().get("LaunchMaximized").toBool())
+ windowSize = "max";
+ else
+ windowSize = QString("%1x%2").
+ arg(m_instance->settings().get("MinecraftWinWidth").toInt()).
+ arg(m_instance->settings().get("MinecraftWinHeight").toInt());
+
+ // window title
+ QString windowTitle;
+ windowTitle.append("MultiMC: ").append(m_instance->name());
+
+ // Java arguments
+ m_arguments.append(splitArgs(m_instance->settings().get("JvmArgs").toString()));
+
+#ifdef OSX
+ // OSX dock icon and name
+ m_arguments << "-Xdock:icon=icon.png";
+ m_arguments << QString("-Xdock:name=\"%1\"").arg(windowTitle);
+#endif
+
+ // lwjgl
+ QString lwjgl = m_instance->lwjglVersion();
+ if (lwjgl != "Mojang")
+ lwjgl = QDir(globalSettings->get("LWJGLDir").toString() + "/" + lwjgl).absolutePath();
+
+ // launcher arguments
+ m_arguments << QString("-Xms%1m").arg(m_instance->settings().get("MinMemAlloc").toInt());
+ m_arguments << QString("-Xmx%1m").arg(m_instance->settings().get("MaxMemAlloc").toInt());
+ m_arguments << "-jar" << LAUNCHER_FILE;
+ m_arguments << m_user;
+ m_arguments << m_session;
+ m_arguments << windowTitle;
+ m_arguments << windowSize;
+ m_arguments << lwjgl;
+}
diff --git a/libmultimc/src/pluginmanager.cpp b/libmultimc/src/pluginmanager.cpp
new file mode 100644
index 00000000..2f066293
--- /dev/null
+++ b/libmultimc/src/pluginmanager.cpp
@@ -0,0 +1,105 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "pluginmanager.h"
+
+#include <QDir>
+#include <QDirIterator>
+#include <QFileInfo>
+#include <QVariant>
+
+#include <QJsonObject>
+
+#include <QtPlugin>
+
+#include "instancetypeinterface.h"
+
+// MultiMC's API version. This must match the "api" field in each plugin's
+// metadata or MultiMC won't consider them valid MultiMC plugin.
+#define MMC_API_VERSION "MultiMC5-API-1"
+
+PluginManager PluginManager::manager;
+
+PluginManager::PluginManager() :
+ QObject(NULL)
+{
+
+}
+
+bool PluginManager::loadPlugins(QString pluginDir)
+{
+ // Delete the loaded plugins and clear the list.
+ for (int i = 0; i < m_plugins.count(); i++)
+ {
+ delete m_plugins[i];
+ }
+ m_plugins.clear();
+
+ qDebug(QString("Loading plugins from directory: %1").
+ arg(pluginDir).toUtf8());
+
+ QDir dir(pluginDir);
+ QDirIterator iter(dir);
+
+ while (iter.hasNext())
+ {
+ QFileInfo pluginFile(dir.absoluteFilePath(iter.next()));
+
+ if (pluginFile.exists() && pluginFile.isFile())
+ {
+ qDebug(QString("Attempting to load plugin: %1").
+ arg(pluginFile.canonicalFilePath()).toUtf8());
+
+ QPluginLoader *pluginLoader = new QPluginLoader(pluginFile.absoluteFilePath());
+
+ QJsonObject pluginInfo = pluginLoader->metaData();
+ QJsonObject pluginMetadata = pluginInfo.value("MetaData").toObject();
+
+ if (pluginMetadata.value("api").toString("") != MMC_API_VERSION)
+ {
+ // If "api" is not specified, it's not a MultiMC plugin.
+ qDebug(QString("Not loading plugin %1. Not a valid MultiMC plugin. "
+ "API: %2").
+ arg(pluginFile.canonicalFilePath(), pluginMetadata.value("api").toString("")).toUtf8());
+ continue;
+ }
+
+ qDebug(QString("Loaded plugin: %1").
+ arg(pluginInfo.value("IID").toString()).toUtf8());
+ m_plugins.push_back(pluginLoader);
+ }
+ }
+
+ return true;
+}
+
+QPluginLoader *PluginManager::getPlugin(int index)
+{
+ return m_plugins[index];
+}
+
+void PluginManager::initInstanceTypes()
+{
+ for (int i = 0; i < m_plugins.count(); i++)
+ {
+ InstanceTypeInterface *instType = qobject_cast<InstanceTypeInterface *>(m_plugins[i]->instance());
+
+ if (instType)
+ {
+ // TODO: Handle errors
+ InstanceLoader::get().registerInstanceType(instType);
+ }
+ }
+}
diff --git a/libmultimc/src/task.cpp b/libmultimc/src/task.cpp
new file mode 100644
index 00000000..d581a1dd
--- /dev/null
+++ b/libmultimc/src/task.cpp
@@ -0,0 +1,56 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "task.h"
+
+Task::Task(QObject *parent) :
+ QThread(parent)
+{
+
+}
+
+QString Task::getStatus() const
+{
+ return status;
+}
+
+void Task::setStatus(const QString &status)
+{
+ this->status = status;
+ emit statusChanged(status);
+}
+
+int Task::getProgress() const
+{
+ return progress;
+}
+
+void Task::setProgress(int progress)
+{
+ this->progress = progress;
+ emit progressChanged(progress);
+}
+
+void Task::startTask()
+{
+ start();
+}
+
+void Task::run()
+{
+ emit taskStarted(this);
+ executeTask();
+ emit taskEnded(this);
+}
diff --git a/libmultimc/src/userinfo.cpp b/libmultimc/src/userinfo.cpp
new file mode 100644
index 00000000..0bb5da11
--- /dev/null
+++ b/libmultimc/src/userinfo.cpp
@@ -0,0 +1,49 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "userinfo.h"
+
+UserInfo::UserInfo(const QString &username, const QString &password, QObject *parent) :
+ QObject(parent)
+{
+ this->m_username = username;
+ this->m_password = password;
+}
+
+UserInfo::UserInfo(const UserInfo &other)
+{
+ this->m_username = other.m_username;
+ this->m_password = other.m_password;
+}
+
+QString UserInfo::username() const
+{
+ return m_username;
+}
+
+void UserInfo::setUsername(const QString &username)
+{
+ this->m_username = username;
+}
+
+QString UserInfo::password() const
+{
+ return m_password;
+}
+
+void UserInfo::setPassword(const QString &password)
+{
+ this->m_password = password;
+}
diff --git a/libmultimc/src/version.cpp b/libmultimc/src/version.cpp
new file mode 100644
index 00000000..eec50e13
--- /dev/null
+++ b/libmultimc/src/version.cpp
@@ -0,0 +1,46 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "version.h"
+
+#include "config.h"
+
+Version Version::current(VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD);
+
+Version::Version(int major, int minor, int revision, int build, QObject *parent) :
+ QObject(parent)
+{
+ this->major = major;
+ this->minor = minor;
+ this->revision = revision;
+ this->build = build;
+}
+
+Version::Version(const Version& ver)
+{
+ this->major = ver.major;
+ this->minor = ver.minor;
+ this->revision = ver.revision;
+ this->build = ver.build;
+}
+
+QString Version::toString() const
+{
+ return QString("%1.%2.%3.%4").arg(
+ QString::number(major),
+ QString::number(minor),
+ QString::number(revision),
+ QString::number(build));
+}