From 13b1b98f7cf8a3b3b2c15dd42f96537b02c00711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sat, 3 Aug 2013 15:57:33 +0200 Subject: [PATCH] WTF, I don't even... --- AppSettings.cpp | 1 - AppVersion.cpp | 8 +- AppVersion.h | 8 +- backend/BaseInstance.cpp | 207 ++++++++----------- backend/BaseInstance.h | 270 +++++-------------------- backend/BaseInstance_p.h | 14 ++ backend/CMakeLists.txt | 2 + backend/InstanceFactory.cpp | 27 ++- backend/InstanceFactory.h | 3 +- backend/LegacyInstance.cpp | 233 +++++++++++++++++++++ backend/LegacyInstance.h | 104 +++++++++- backend/LegacyInstance_p.h | 10 + backend/MinecraftProcess.cpp | 97 ++------- backend/MinecraftProcess.h | 35 +--- backend/MinecraftVersion.cpp | 14 -- backend/MinecraftVersion.h | 14 -- backend/OneSixInstance.cpp | 18 ++ backend/OneSixInstance.h | 12 +- backend/OneSixInstance_p.h | 8 + backend/lists/MinecraftVersionList.cpp | 152 +------------- backend/lists/MinecraftVersionList.h | 6 - backend/tasks/GameUpdateTask.cpp | 81 +------- backend/tasks/GameUpdateTask.h | 2 - gui/instancemodel.cpp | 2 +- gui/instancesettings.cpp | 16 +- gui/mainwindow.cpp | 43 ++-- gui/mainwindow.h | 4 +- gui/settingsdialog.cpp | 2 - main.cpp | 11 +- 29 files changed, 632 insertions(+), 772 deletions(-) create mode 100644 backend/BaseInstance_p.h create mode 100644 backend/LegacyInstance_p.h create mode 100644 backend/OneSixInstance_p.h diff --git a/AppSettings.cpp b/AppSettings.cpp index 835d42ac..9a4cb99f 100644 --- a/AppSettings.cpp +++ b/AppSettings.cpp @@ -47,7 +47,6 @@ AppSettings::AppSettings(QObject *parent) : // 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)); diff --git a/AppVersion.cpp b/AppVersion.cpp index 2db3da26..86b00920 100644 --- a/AppVersion.cpp +++ b/AppVersion.cpp @@ -17,9 +17,9 @@ #include "config.h" -Version Version::current(VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD); +AppVersion AppVersion::current(VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD); -Version::Version(int major, int minor, int revision, int build, QObject *parent) : +AppVersion::AppVersion(int major, int minor, int revision, int build, QObject *parent) : QObject(parent) { this->major = major; @@ -28,7 +28,7 @@ Version::Version(int major, int minor, int revision, int build, QObject *parent) this->build = build; } -Version::Version(const Version& ver) +AppVersion::AppVersion(const AppVersion& ver) { this->major = ver.major; this->minor = ver.minor; @@ -36,7 +36,7 @@ Version::Version(const Version& ver) this->build = ver.build; } -QString Version::toString() const +QString AppVersion::toString() const { return QString("%1.%2.%3.%4").arg( QString::number(major), diff --git a/AppVersion.h b/AppVersion.h index 504f1d17..86f53950 100644 --- a/AppVersion.h +++ b/AppVersion.h @@ -20,14 +20,14 @@ /*! * \brief The Version class represents a MultiMC version number. */ -class Version : public QObject +class AppVersion : public QObject { Q_OBJECT public: - explicit Version(int major = 0, int minor = 0, int revision = 0, + explicit AppVersion(int major = 0, int minor = 0, int revision = 0, int build = 0, QObject *parent = 0); - Version(const Version& ver); + AppVersion(const AppVersion& ver); /*! * \brief Converts the Version to a string. @@ -60,6 +60,6 @@ public: */ int build; - static Version current; + static AppVersion current; }; diff --git a/backend/BaseInstance.cpp b/backend/BaseInstance.cpp index c2ffa664..d94f3de9 100644 --- a/backend/BaseInstance.cpp +++ b/backend/BaseInstance.cpp @@ -14,6 +14,7 @@ */ #include "BaseInstance.h" +#include "BaseInstance_p.h" #include @@ -24,56 +25,52 @@ #include "pathutils.h" #include -BaseInstance::BaseInstance(const QString &rootDir, QObject *parent) : - QObject(parent) + +BaseInstance::BaseInstance( BaseInstancePrivate* d_in, + const QString& rootDir, + SettingsObject* settings_obj, + QObject* parent + ) +:inst_d(d_in), QObject(parent) { - m_rootDir = rootDir; - m_settings = new INISettingsObject(PathCombine(rootDir, "instance.cfg"), this); + I_D(BaseInstance); + d->m_settings = settings_obj; + d->m_rootDir = rootDir; 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("ShouldUpdate", false)); - settings().registerSetting(new Setting("JarVersion", "Unknown")); - settings().registerSetting(new Setting("LwjglVersion", "2.9.0")); - settings().registerSetting(new Setting("IntendedJarVersion", "")); settings().registerSetting(new Setting("lastLaunchTime", 0)); // Java Settings + settings().registerSetting(new Setting("OverrideJava", false)); 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"))); + settings().registerSetting(new Setting("OverrideCommands", false)); + settings().registerSetting(new OverrideSetting("PreLaunchCommand", globalSettings->getSetting("PreLaunchCommand"))); + settings().registerSetting(new OverrideSetting("PostExitCommand", globalSettings->getSetting("PostExitCommand"))); // Window Size - settings().registerSetting(new OverrideSetting("LaunchCompatMode", globalSettings->getSetting("LaunchCompatMode"))); + settings().registerSetting(new Setting("OverrideWindow", false)); settings().registerSetting(new OverrideSetting("LaunchMaximized", globalSettings->getSetting("LaunchMaximized"))); settings().registerSetting(new OverrideSetting("MinecraftWinWidth", globalSettings->getSetting("MinecraftWinWidth"))); settings().registerSetting(new OverrideSetting("MinecraftWinHeight", globalSettings->getSetting("MinecraftWinHeight"))); // Memory + settings().registerSetting(new Setting("OverrideMemory", false)); settings().registerSetting(new OverrideSetting("MinMemAlloc", globalSettings->getSetting("MinMemAlloc"))); settings().registerSetting(new OverrideSetting("MaxMemAlloc", globalSettings->getSetting("MaxMemAlloc"))); // Auto login + settings().registerSetting(new Setting("OverrideLogin", false)); settings().registerSetting(new OverrideSetting("AutoLogin", globalSettings->getSetting("AutoLogin"))); // Console + settings().registerSetting(new Setting("OverrideConsole", false)); settings().registerSetting(new OverrideSetting("ShowConsole", globalSettings->getSetting("ShowConsole"))); settings().registerSetting(new OverrideSetting("AutoCloseConsole", globalSettings->getSetting("AutoCloseConsole"))); - - // Overrides - settings().registerSetting(new Setting("OverrideConsole", false)); - settings().registerSetting(new Setting("OverrideWindow", false)); - settings().registerSetting(new Setting("OverrideLogin", false)); - settings().registerSetting(new Setting("OverrideMemory", false)); - settings().registerSetting(new Setting("OverrideJava", false)); - settings().registerSetting(new Setting("OverrideCommands", false)); } QString BaseInstance::id() const @@ -81,9 +78,17 @@ QString BaseInstance::id() const return QFileInfo(rootDir()).fileName(); } +QString BaseInstance::instanceType() const +{ + I_D(BaseInstance); + return d->m_settings->get("InstanceType").toString(); +} + + QString BaseInstance::rootDir() const { - return m_rootDir; + I_D(BaseInstance); + return d->m_rootDir; } InstanceList *BaseInstance::instList() const @@ -94,106 +99,72 @@ InstanceList *BaseInstance::instList() const return NULL; } -QString BaseInstance::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 BaseInstance::instModsDir() const -{ - return PathCombine(rootDir(), "instMods"); -} - -QString BaseInstance::binDir() const -{ - return PathCombine(minecraftDir(), "bin"); -} - -QString BaseInstance::savesDir() const -{ - return PathCombine(minecraftDir(), "saves"); -} - -QString BaseInstance::mlModsDir() const -{ - return PathCombine(minecraftDir(), "mods"); -} - -QString BaseInstance::coreModsDir() const -{ - return PathCombine(minecraftDir(), "coremods"); -} - -QString BaseInstance::resourceDir() const -{ - return PathCombine(minecraftDir(), "resources"); -} - -QString BaseInstance::screenshotsDir() const -{ - return PathCombine(minecraftDir(), "screenshots"); -} - -QString BaseInstance::texturePacksDir() const -{ - return PathCombine(minecraftDir(), "texturepacks"); -} - -QString BaseInstance::mcJar() const -{ - return PathCombine(binDir(), "minecraft.jar"); -} - -QString BaseInstance::mcBackup() const -{ - return PathCombine(binDir(), "mcbackup.jar"); -} - -QString BaseInstance::modListFile() const -{ - return PathCombine(rootDir(), "modlist"); -} - InstVersionList *BaseInstance::versionList() const { return &MinecraftVersionList::getMainList(); } -bool BaseInstance::shouldUpdateCurrentVersion() const -{ - QFileInfo jar(mcJar()); - return jar.lastModified().toUTC().toMSecsSinceEpoch() != lastCurrentVersionUpdate(); -} - -void BaseInstance::updateCurrentVersion(bool keepCurrent) -{ - QFileInfo jar(mcJar()); - - if(!jar.exists()) - { - setLastCurrentVersionUpdate(0); - setCurrentVersion("Unknown"); - return; - } - - qint64 time = jar.lastModified().toUTC().toMSecsSinceEpoch(); - - setLastCurrentVersionUpdate(time); - if (!keepCurrent) - { - // TODO: Implement GetMinecraftJarVersion function. - QString newVersion = "Unknown";//javautils::GetMinecraftJarVersion(jar.absoluteFilePath()); - setCurrentVersion(newVersion); - } -} - SettingsObject &BaseInstance::settings() const { - return *m_settings; + I_D(BaseInstance); + return *d->m_settings; +} + +qint64 BaseInstance::lastLaunch() const +{ + I_D(BaseInstance); + return d->m_settings->get ( "lastLaunchTime" ).value(); +} +void BaseInstance::setLastLaunch ( qint64 val ) +{ + I_D(BaseInstance); + d->m_settings->set ( "lastLaunchTime", val ); + emit propertiesChanged ( this ); +} + +void BaseInstance::setGroup ( QString val ) +{ + I_D(BaseInstance); + d->m_group = val; + emit propertiesChanged ( this ); +} +QString BaseInstance::group() const +{ + I_D(BaseInstance); + return d->m_group; +} + +void BaseInstance::setNotes ( QString val ) +{ + I_D(BaseInstance); + d->m_settings->set ( "notes", val ); +} +QString BaseInstance::notes() const +{ + I_D(BaseInstance); + return d->m_settings->get ( "notes" ).toString(); +} + +void BaseInstance::setIconKey ( QString val ) +{ + I_D(BaseInstance); + d->m_settings->set ( "iconKey", val ); + emit propertiesChanged ( this ); +} +QString BaseInstance::iconKey() const +{ + I_D(BaseInstance); + return d->m_settings->get ( "iconKey" ).toString(); +} + +void BaseInstance::setName ( QString val ) +{ + I_D(BaseInstance); + d->m_settings->set ( "name", val ); + emit propertiesChanged ( this ); +} +QString BaseInstance::name() const +{ + I_D(BaseInstance); + return d->m_settings->get ( "name" ).toString(); } diff --git a/backend/BaseInstance.h b/backend/BaseInstance.h index 51f55b5e..088075f2 100644 --- a/backend/BaseInstance.h +++ b/backend/BaseInstance.h @@ -25,7 +25,10 @@ #include "libmmc_config.h" +class MinecraftProcess; +class GameUpdateTask; class InstanceList; +class BaseInstancePrivate; /*! * \brief Base class for instances. @@ -38,128 +41,21 @@ class InstanceList; class LIBMULTIMC_EXPORT BaseInstance : public QObject { Q_OBJECT - - // Properties - /*! - * The instance's ID. - * This is a unique identifier string that is, by default, set to the - * instance's folder name. It's not always the instance's folder name, - * however, as any class deriving from Instance can override the id() - * method and change how the ID is determined. The instance's ID should - * always remain constant. Undefined behavior results if an already loaded - * instance's ID changes. - */ - Q_PROPERTY(QString id READ id STORED false) - - //! Path to the instance's root directory. - Q_PROPERTY(QString rootDir READ rootDir) - - //! The name of the instance that is displayed to the user. - Q_PROPERTY(QString name READ name WRITE setName) - - //! The instance's icon key. - Q_PROPERTY(QString iconKey READ iconKey WRITE setIconKey) - - //! The instance's notes. - Q_PROPERTY(QString notes READ notes WRITE setNotes) - - //! The instance's group. - Q_PROPERTY(QString group READ group WRITE setGroup) - - /*! - * Gets the time that the instance was last launched. - * Stored in milliseconds since epoch. - * This value is usually used for things like sorting instances by the time - * they were last launched. - */ - Q_PROPERTY(qint64 lastLaunch READ lastLaunch WRITE setLastLaunch) - - /*! - * Whether or not the instance's minecraft.jar needs to be rebuilt. - * If this is true, when the instance launches, its jar mods will be - * re-added to a fresh minecraft.jar file. - */ - Q_PROPERTY(bool shouldRebuild READ shouldRebuild WRITE setShouldRebuild) - - /*! - * Whether or not Minecraft should be downloaded when the instance is launched. - * This returns true if shouldForceUpdate game is true or if the intended and - * current versions don't match. - */ - Q_PROPERTY(bool shouldUpdate READ shouldUpdate WRITE setShouldUpdate) - - /*! - * The instance's current version. - * This value represents the instance's current version. If this value is - * different from the intendedVersion, the instance should be updated. - * \warning Don't change this value unless you know what you're doing. - */ - Q_PROPERTY(QString currentVersion READ currentVersion WRITE setCurrentVersion) - - /*! - * The version that the user has set for this instance to use. - * If this is not the same as currentVersion, the instance's game updater - * will be run on launch. - */ - Q_PROPERTY(QString intendedVersion READ intendedVersion WRITE setIntendedVersion) - - //! The version of LWJGL that this instance uses. - Q_PROPERTY(QString lwjglVersion READ lwjglVersion WRITE setLWJGLVersion) - - - /*! - * Gets the last time that the current version was checked. - * This is checked against the last modified time on the jar file to see if - * the current version needs to be checked again. - */ - Q_PROPERTY(qint64 lastCurrentVersionUpdate READ lastCurrentVersionUpdate WRITE setLastCurrentVersionUpdate) - - // Dirs - //! Path to the instance's .minecraft folder. - Q_PROPERTY(QString minecraftDir READ minecraftDir STORED false) - - //! Path to the instance's instMods folder. - Q_PROPERTY(QString instModsDir READ instModsDir STORED false) - - //! Path to the instance's bin folder. - Q_PROPERTY(QString binDir READ binDir STORED false) - - //! Path to the instance's saves folder. - Q_PROPERTY(QString savesDir READ savesDir STORED false) - - //! Path to the instance's mods folder (.minecraft/mods) - Q_PROPERTY(QString mlModsDir READ mlModsDir STORED false) - - //! Path to the instance's coremods folder. - Q_PROPERTY(QString coreModsDir READ coreModsDir STORED false) - - //! Path to the instance's resources folder. - Q_PROPERTY(QString resourceDir READ resourceDir STORED false) - - //! Path to the instance's screenshots folder. - Q_PROPERTY(QString screenshotsDir READ screenshotsDir STORED false) - - //! Path to the instance's texturepacks folder. - Q_PROPERTY(QString texturePacksDir READ texturePacksDir STORED false) - - - // Files - //! Path to the instance's minecraft.jar - Q_PROPERTY(QString mcJar READ mcJar STORED false) - - //! Path to the instance's mcbackup.jar - Q_PROPERTY(QString mcBackup READ mcBackup STORED false) - - //! Path to the instance's modlist file. - Q_PROPERTY(QString modListFile READ modListFile STORED false) - +protected: + /// no-touchy! + BaseInstance(BaseInstancePrivate * d, const QString &rootDir, SettingsObject * settings, QObject *parent = 0); public: - explicit BaseInstance(const QString &rootDir, QObject *parent = 0); + /// virtual destructor to make sure the destruction is COMPLETE + virtual ~BaseInstance() {}; - //////// STUFF //////// - virtual QString id() const; + /// The instance's ID. The ID SHALL be determined by MMC internally. The ID IS guaranteed to be unique. + QString id() const; - virtual QString rootDir() const; + /// get the type of this instance + QString instanceType() const; + + /// Path to the instance's root directory. + QString rootDir() const; /*! * \brief Gets the instance list that this instance is a part of. @@ -167,128 +63,52 @@ public: * (the parent is not an InstanceList). * \return A pointer to the InstanceList containing this instance. */ - virtual InstanceList *instList() const; + InstanceList *instList() const; //////// INSTANCE INFO //////// - //// General Info //// - virtual QString name() const { return settings().get("name").toString(); } - virtual void setName(QString val) - { - settings().set("name", val); - emit propertiesChanged(this); - } + /// The name of the instance that is displayed to the user. + QString name() const; - virtual QString iconKey() const { return settings().get("iconKey").toString(); } - virtual void setIconKey(QString val) - { - settings().set("iconKey", val); - emit propertiesChanged(this); - } + /// Set the name of the instance that is displayed to the user. + void setName(QString val); - virtual QString notes() const { return settings().get("notes").toString(); } - virtual void setNotes(QString val) { settings().set("notes", val); } + /// The instance's icon key. + QString iconKey() const; - virtual QString group() const { return m_group; } - virtual void setGroup(QString val) - { - m_group = val; - emit propertiesChanged(this); - } + /// Set the instance's icon key. + void setIconKey(QString val); - virtual bool shouldRebuild() const { return settings().get("NeedsRebuild").toBool(); } - virtual void setShouldRebuild(bool val) { settings().set("NeedsRebuild", val); } + //! The instance's notes. + QString notes() const; + /// set the instance notes text + void setNotes(QString val); - //// Version Stuff //// + //! The instance's group. + QString group() const; - virtual QString currentVersion() const { return settings().get("JarVersion").toString(); } - virtual void setCurrentVersion(QString val) { settings().set("JarVersion", val); } + /// set the instance group + void setGroup(QString val); - virtual QString lwjglVersion() const { return settings().get("LwjglVersion").toString(); } - virtual void setLWJGLVersion(QString val) { settings().set("LwjglVersion", val); } - - virtual QString intendedVersion() const { return settings().get("IntendedJarVersion").toString(); } - virtual void setIntendedVersion(QString val) { settings().set("IntendedJarVersion", val); } - - virtual bool shouldUpdate() const - { - QVariant var = settings().get("ShouldUpdate"); - if(!var.isValid() || var.toBool() == false) - { - return intendedVersion() != currentVersion(); - } - return true; - } - virtual void setShouldUpdate(bool val) { settings().set("ShouldUpdate", val); } - //// Timestamps //// - virtual qint64 lastLaunch() const { return settings().get("lastLaunchTime").value(); } - virtual void setLastLaunch(qint64 val = QDateTime::currentMSecsSinceEpoch()) - { - settings().set("lastLaunchTime", val); - emit propertiesChanged(this); - } - - virtual qint64 lastCurrentVersionUpdate() const { return settings().get("lastVersionUpdate").value(); } - virtual void setLastCurrentVersionUpdate(qint64 val) { settings().set("lastVersionUpdate", val); } - - ////// Directories ////// - QString minecraftDir() const; - QString instModsDir() const; - QString binDir() const; - QString savesDir() const; - QString mlModsDir() const; - QString coreModsDir() const; - QString resourceDir() const; - QString screenshotsDir() const; - QString texturePacksDir() const; + /** + * Gets the time that the instance was last launched. + * Stored in milliseconds since epoch. + */ + qint64 lastLaunch() const; + /// Sets the last launched time to 'val' milliseconds since epoch + void setLastLaunch(qint64 val = QDateTime::currentMSecsSinceEpoch()); - ////// Files ////// - QString mcJar() const; - QString mcBackup() const; - QString modListFile() const; - - - //////// LISTS, LISTS, AND MORE LISTS //////// /*! * \brief Gets a pointer to this instance's version list. * \return A pointer to the available version list for this instance. */ virtual InstVersionList *versionList() const; - - //////// OTHER FUNCTIONS //////// - - //// Version System //// - - /*! - * \brief Checks whether or not the currentVersion of the instance needs to be updated. - * If this returns true, updateCurrentVersion is called. In the - * standard instance, this is determined by checking a timestamp - * stored in the instance config file against the last modified time of Minecraft.jar. - * \return True if updateCurrentVersion() should be called. - */ - virtual bool shouldUpdateCurrentVersion() const; - - /*! - * \brief Updates the current version. - * This function should first set the current version timestamp - * (setCurrentVersionTimestamp()) to the current time. Next, if - * keepCurrent is false, this function should check what the - * instance's current version is and call setCurrentVersion() to - * update it. This function will automatically be called when the - * instance is loaded if shouldUpdateCurrentVersion returns true. - * \param keepCurrent If true, only the version timestamp will be updated. - */ - virtual void updateCurrentVersion(bool keepCurrent = false); - - - //// Settings System //// - /*! * \brief Gets this instance's settings object. * This settings object stores instance-specific settings. @@ -296,16 +116,20 @@ public: */ virtual SettingsObject &settings() const; + /// returns a valid update task if update is needed, NULL otherwise + virtual GameUpdateTask* doUpdate() = 0; + + /// returns a valid minecraft process, ready for launch + virtual MinecraftProcess* prepareForLaunch(QString user, QString session) = 0; + signals: /*! * \brief Signal emitted when properties relevant to the instance view change */ void propertiesChanged(BaseInstance * inst); -private: - QString m_rootDir; - QString m_group; - SettingsObject *m_settings; +protected: + QSharedPointer inst_d; }; // pointer for lazy people diff --git a/backend/BaseInstance_p.h b/backend/BaseInstance_p.h new file mode 100644 index 00000000..a30916a4 --- /dev/null +++ b/backend/BaseInstance_p.h @@ -0,0 +1,14 @@ +#pragma once +#include +#include + +class BaseInstance; + +#define I_D(Class) Class##Private * const d = (Class##Private * const) inst_d.data() + +struct BaseInstancePrivate +{ + QString m_rootDir; + QString m_group; + SettingsObject *m_settings; +}; \ No newline at end of file diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index a17b7dfe..9bd07c01 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -89,3 +89,5 @@ add_definitions(-DLIBMULTIMC_LIBRARY) add_library(backend SHARED ${LIBINST_SOURCES} ${LIBINST_HEADERS}) qt5_use_modules(backend Core Network Xml) target_link_libraries(backend libUtil libSettings) + + diff --git a/backend/InstanceFactory.cpp b/backend/InstanceFactory.cpp index 318650ae..ee582d3f 100644 --- a/backend/InstanceFactory.cpp +++ b/backend/InstanceFactory.cpp @@ -19,8 +19,12 @@ #include #include "BaseInstance.h" +#include "LegacyInstance.h" +#include "OneSixInstance.h" #include "inifile.h" +#include +#include #include "pathutils.h" @@ -34,12 +38,25 @@ InstanceFactory::InstanceFactory() : InstanceFactory::InstLoadError InstanceFactory::loadInstance(BaseInstance *&inst, const QString &instDir) { - BaseInstance *loadedInst = new BaseInstance(instDir, this); + auto m_settings = new INISettingsObject(PathCombine(instDir, "instance.cfg")); - // TODO: Sanity checks to verify that the instance is valid. + m_settings->registerSetting(new Setting("InstanceType", "Legacy")); - inst = loadedInst; + QString inst_type = m_settings->get("InstanceType").toString(); + //FIXME: replace with a map lookup, where instance classes register their types + if(inst_type == "Legacy") + { + inst = new LegacyInstance(instDir, m_settings, this); + } + else if(inst_type == "OneSix") + { + inst = new OneSixInstance(instDir, m_settings, this); + } + else + { + return InstanceFactory::UnknownLoadError; + } return NoLoadError; } @@ -53,8 +70,8 @@ InstanceFactory::InstCreateError InstanceFactory::createInstance(BaseInstance *& { return InstanceFactory::CantCreateDir; } - - inst = new BaseInstance(instDir, this); + return InstanceFactory::UnknownCreateError; + //inst = new BaseInstance(instDir, this); //FIXME: really, how do you even know? return InstanceFactory::NoCreateError; diff --git a/backend/InstanceFactory.h b/backend/InstanceFactory.h index 0dd4c5d8..26857ef9 100644 --- a/backend/InstanceFactory.h +++ b/backend/InstanceFactory.h @@ -51,10 +51,9 @@ public: }; /*! - * \brief Creates an instance with the given type and stores it in inst. + * \brief Creates a stub instance * * \param inst Pointer to store the created instance in. - * \param type The type of instance to create. * \param instDir The instance's directory. * \return An InstCreateError error code. * - InstExists if the given instance directory is already an instance. diff --git a/backend/LegacyInstance.cpp b/backend/LegacyInstance.cpp index e69de29b..001400e5 100644 --- a/backend/LegacyInstance.cpp +++ b/backend/LegacyInstance.cpp @@ -0,0 +1,233 @@ +#include "LegacyInstance.h" +#include "LegacyInstance_p.h" +#include "MinecraftProcess.h" +#include +#include +#include +#include +#include +#include + +#define LAUNCHER_FILE "MultiMCLauncher.jar" + +LegacyInstance::LegacyInstance(const QString& rootDir, SettingsObject* settings, QObject* parent) + :BaseInstance( new LegacyInstancePrivate(),rootDir, settings, parent) +{ + settings->registerSetting(new Setting("NeedsRebuild", true)); + settings->registerSetting(new Setting("ShouldUpdate", false)); + settings->registerSetting(new Setting("JarVersion", "Unknown")); + settings->registerSetting(new Setting("LwjglVersion", "2.9.0")); + settings->registerSetting(new Setting("IntendedJarVersion", "")); +} + +QString LegacyInstance::minecraftDir() const +{ + QFileInfo mcDir(PathCombine(rootDir(), "minecraft")); + QFileInfo dotMCDir(PathCombine(rootDir(), ".minecraft")); + + if (dotMCDir.exists() && !mcDir.exists()) + return dotMCDir.filePath(); + else + return mcDir.filePath(); +} + +GameUpdateTask* LegacyInstance::doUpdate() +{ + // legacy instances no longer update + return nullptr; +} + +MinecraftProcess* LegacyInstance::prepareForLaunch(QString user, QString session) +{ + MinecraftProcess * proc = new MinecraftProcess(this); + + // FIXME: extract the icon + // QImage(":/icons/instances/" + iconKey()).save(PathCombine(minecraftDir(), "icon.png")); + + // extract the legacy launcher + QFile(":/launcher/launcher.jar").copy(PathCombine(minecraftDir(), LAUNCHER_FILE)); + + // set the process arguments + { + QStringList args; + + // window size + QString windowSize; + if (settings().get("LaunchMaximized").toBool()) + windowSize = "max"; + else + windowSize = QString("%1x%2"). + arg(settings().get("MinecraftWinWidth").toInt()). + arg(settings().get("MinecraftWinHeight").toInt()); + + // window title + QString windowTitle; + windowTitle.append("MultiMC: ").append(name()); + + // Java arguments + args.append(Util::Commandline::splitArgs(settings().get("JvmArgs").toString())); + +#ifdef OSX + // OSX dock icon and name + args << "-Xdock:icon=icon.png"; + args << QString("-Xdock:name=\"%1\"").arg(windowTitle); +#endif + + QString lwjgl = QDir(globalSettings->get("LWJGLDir").toString() + "/" + lwjglVersion()).absolutePath(); + + // launcher arguments + args << QString("-Xms%1m").arg(settings().get("MinMemAlloc").toInt()); + args << QString("-Xmx%1m").arg(settings().get("MaxMemAlloc").toInt()); + args << "-jar" << LAUNCHER_FILE; + args << user; + args << session; + args << windowTitle; + args << windowSize; + args << lwjgl; + proc->setMinecraftArguments(args); + } + + // set the process work path + proc->setMinecraftWorkdir(minecraftDir()); + + return proc; +} + + +QString LegacyInstance::instModsDir() const +{ + return PathCombine(rootDir(), "instMods"); +} + +QString LegacyInstance::binDir() const +{ + return PathCombine(minecraftDir(), "bin"); +} + +QString LegacyInstance::savesDir() const +{ + return PathCombine(minecraftDir(), "saves"); +} + +QString LegacyInstance::mlModsDir() const +{ + return PathCombine(minecraftDir(), "mods"); +} + +QString LegacyInstance::coreModsDir() const +{ + return PathCombine(minecraftDir(), "coremods"); +} + +QString LegacyInstance::resourceDir() const +{ + return PathCombine(minecraftDir(), "resources"); +} + +QString LegacyInstance::mcJar() const +{ + return PathCombine(binDir(), "minecraft.jar"); +} + +QString LegacyInstance::mcBackup() const +{ + return PathCombine(binDir(), "mcbackup.jar"); +} + +QString LegacyInstance::modListFile() const +{ + return PathCombine(rootDir(), "modlist"); +} + +bool LegacyInstance::shouldUpdateCurrentVersion() const +{ + QFileInfo jar(mcJar()); + return jar.lastModified().toUTC().toMSecsSinceEpoch() != lastCurrentVersionUpdate(); +} + +void LegacyInstance::updateCurrentVersion(bool keepCurrent) +{ + QFileInfo jar(mcJar()); + + if(!jar.exists()) + { + setLastCurrentVersionUpdate(0); + setCurrentVersion("Unknown"); + return; + } + + qint64 time = jar.lastModified().toUTC().toMSecsSinceEpoch(); + + setLastCurrentVersionUpdate(time); + if (!keepCurrent) + { + // TODO: Implement GetMinecraftJarVersion function. + QString newVersion = "Unknown";//javautils::GetMinecraftJarVersion(jar.absoluteFilePath()); + setCurrentVersion(newVersion); + } +} +qint64 LegacyInstance::lastCurrentVersionUpdate() const +{ + I_D(LegacyInstance); + return d->m_settings->get ( "lastVersionUpdate" ).value(); +} +void LegacyInstance::setLastCurrentVersionUpdate ( qint64 val ) +{ + I_D(LegacyInstance); + d->m_settings->set ( "lastVersionUpdate", val ); +} +bool LegacyInstance::shouldRebuild() const +{ + I_D(LegacyInstance); + return d->m_settings->get ( "NeedsRebuild" ).toBool(); +} +void LegacyInstance::setShouldRebuild ( bool val ) +{ + I_D(LegacyInstance); + d->m_settings->set ( "NeedsRebuild", val ); +} +QString LegacyInstance::currentVersion() const +{ + I_D(LegacyInstance); + return d->m_settings->get ( "JarVersion" ).toString(); +} +void LegacyInstance::setCurrentVersion ( QString val ) +{ + I_D(LegacyInstance); + d->m_settings->set ( "JarVersion", val ); +} +QString LegacyInstance::lwjglVersion() const +{ + I_D(LegacyInstance); + return d->m_settings->get ( "LwjglVersion" ).toString(); +} +void LegacyInstance::setLWJGLVersion ( QString val ) +{ + I_D(LegacyInstance); + d->m_settings->set ( "LwjglVersion", val ); +} +QString LegacyInstance::intendedVersion() const +{ + I_D(LegacyInstance); + return d->m_settings->get ( "IntendedJarVersion" ).toString(); +} +void LegacyInstance::setIntendedVersion ( QString val ) +{ + I_D(LegacyInstance); + d->m_settings->set ( "IntendedJarVersion", val ); +} +bool LegacyInstance::shouldUpdate() const +{ + I_D(LegacyInstance); + QVariant var = d->m_settings->get ( "ShouldUpdate" ); + if ( !var.isValid() || var.toBool() == false ) + { + return intendedVersion() != currentVersion(); + } + return true; +} +void LegacyInstance::setShouldUpdate ( bool val ) +{ + I_D(LegacyInstance); + d->m_settings->set ( "ShouldUpdate", val ); +} diff --git a/backend/LegacyInstance.h b/backend/LegacyInstance.h index 7b9637ef..ef449b79 100644 --- a/backend/LegacyInstance.h +++ b/backend/LegacyInstance.h @@ -1 +1,103 @@ -#pragma once \ No newline at end of file +#pragma once + +#include "BaseInstance.h" + +class LIBMULTIMC_EXPORT LegacyInstance : public BaseInstance +{ + Q_OBJECT +public: + + explicit LegacyInstance(const QString &rootDir, SettingsObject * settings, QObject *parent = 0); + + /// Path to the instance's minecraft.jar + QString mcJar() const; + + //! Path to the instance's mcbackup.jar + QString mcBackup() const; + + //! Path to the instance's modlist file. + QString modListFile() const; + + ////// Directories ////// + QString minecraftDir() const; + QString instModsDir() const; + QString binDir() const; + QString savesDir() const; + QString mlModsDir() const; + QString coreModsDir() const; + QString resourceDir() const; + + /*! + * \brief Checks whether or not the currentVersion of the instance needs to be updated. + * If this returns true, updateCurrentVersion is called. In the + * standard instance, this is determined by checking a timestamp + * stored in the instance config file against the last modified time of Minecraft.jar. + * \return True if updateCurrentVersion() should be called. + */ + bool shouldUpdateCurrentVersion() const; + + /*! + * \brief Updates the current version. + * This function should first set the current version timestamp + * (setCurrentVersionTimestamp()) to the current time. Next, if + * keepCurrent is false, this function should check what the + * instance's current version is and call setCurrentVersion() to + * update it. This function will automatically be called when the + * instance is loaded if shouldUpdateCurrentVersion returns true. + * \param keepCurrent If true, only the version timestamp will be updated. + */ + void updateCurrentVersion(bool keepCurrent = false); + + /*! + * Gets the last time that the current version was checked. + * This is checked against the last modified time on the jar file to see if + * the current version needs to be checked again. + */ + qint64 lastCurrentVersionUpdate() const; + void setLastCurrentVersionUpdate(qint64 val); + + + /*! + * Whether or not the instance's minecraft.jar needs to be rebuilt. + * If this is true, when the instance launches, its jar mods will be + * re-added to a fresh minecraft.jar file. + */ + bool shouldRebuild() const; + void setShouldRebuild(bool val); + + + /*! + * The instance's current version. + * This value represents the instance's current version. If this value is + * different from the intendedVersion, the instance should be updated. + * \warning Don't change this value unless you know what you're doing. + */ + QString currentVersion() const; + void setCurrentVersion(QString val); + + //! The version of LWJGL that this instance uses. + QString lwjglVersion() const; + void setLWJGLVersion(QString val); + + /*! + * The version that the user has set for this instance to use. + * If this is not the same as currentVersion, the instance's game updater + * will be run on launch. + */ + QString intendedVersion() const; + void setIntendedVersion(QString val); + + /*! + * Whether or not Minecraft should be downloaded when the instance is launched. + * This returns true if shouldForceUpdate game is true or if the intended and + * current versions don't match. + */ + bool shouldUpdate() const; + void setShouldUpdate(bool val); + + /// return a valid GameUpdateTask if an update is needed, return NULL otherwise + virtual GameUpdateTask* doUpdate(); + + /// prepare the instance for launch and return a constructed MinecraftProcess instance + virtual MinecraftProcess* prepareForLaunch( QString user, QString session ); +}; \ No newline at end of file diff --git a/backend/LegacyInstance_p.h b/backend/LegacyInstance_p.h new file mode 100644 index 00000000..ac367e20 --- /dev/null +++ b/backend/LegacyInstance_p.h @@ -0,0 +1,10 @@ +#pragma once +#include +#include +#include "BaseInstance_p.h" + +class BaseInstance; + +struct LegacyInstancePrivate: public BaseInstancePrivate +{ +}; \ No newline at end of file diff --git a/backend/MinecraftProcess.cpp b/backend/MinecraftProcess.cpp index e53feb5b..e6ea0034 100644 --- a/backend/MinecraftProcess.cpp +++ b/backend/MinecraftProcess.cpp @@ -29,29 +29,11 @@ #include "pathutils.h" #include "cmdutils.h" -#define LAUNCHER_FILE "MultiMCLauncher.jar" #define IBUS "@im=ibus" -// prepare tools -inline void MinecraftProcess::extractIcon(BaseInstance *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(BaseInstance *inst) -{ - extractLauncher(PathCombine(inst->minecraftDir(), LAUNCHER_FILE)); - extractIcon(inst, PathCombine(inst->minecraftDir(), "icon.png")); -} - // constructor -MinecraftProcess::MinecraftProcess(BaseInstance *inst, QString user, QString session) : - m_instance(inst), m_user(user), m_session(session) +MinecraftProcess::MinecraftProcess( BaseInstance* inst ) : + m_instance(inst) { connect(this, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(finish(int, QProcess::ExitStatus))); @@ -72,16 +54,24 @@ MinecraftProcess::MinecraftProcess(BaseInstance *inst, QString user, QString ses 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())); } +void MinecraftProcess::setMinecraftArguments ( QStringList args ) +{ + m_args = args; +} + +void MinecraftProcess::setMinecraftWorkdir ( QString path ) +{ + QDir mcDir(path); + this->setWorkingDirectory(mcDir.absolutePath()); + m_prepostlaunchprocess.setWorkingDirectory(mcDir.absolutePath()); +} + + // console window void MinecraftProcess::on_stdErr() { @@ -144,10 +134,6 @@ void MinecraftProcess::finish(int code, ExitStatus status) //TODO: error handling } } - -// if (m_console != nullptr) -// m_console->setMayClose(true); - emit ended(); } @@ -166,64 +152,17 @@ void MinecraftProcess::launch() m_instance->setLastLaunch(); - prepare(m_instance); - - genArgs(); - emit log(QString("Minecraft folder is: '%1'").arg(workingDirectory())); QString JavaPath = m_instance->settings().get("JavaPath").toString(); emit log(QString("Java path: '%1'").arg(JavaPath)); - emit log(QString("Arguments: '%1'").arg(m_arguments.join("' '"))); - start(JavaPath, m_arguments); + emit log(QString("Arguments: '%1'").arg(m_args.join("' '"))); + start(JavaPath, m_args); if (!waitForStarted()) { emit log("Could not launch minecraft!"); return; //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(Util::Commandline::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 = QDir(globalSettings->get("LWJGLDir").toString() + "/" + - m_instance->lwjglVersion()).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/backend/MinecraftProcess.h b/backend/MinecraftProcess.h index c846f5f4..756d2de5 100644 --- a/backend/MinecraftProcess.h +++ b/backend/MinecraftProcess.h @@ -49,36 +49,18 @@ public: /** * @brief MinecraftProcess constructor * @param inst the Instance pointer to launch - * @param user the minecraft username - * @param session the minecraft session id - * @param console the instance console window */ - MinecraftProcess(BaseInstance *inst, QString user, QString session); + MinecraftProcess(BaseInstance *inst); /** * @brief launch minecraft */ void launch(); - /** - * @brief extract the instance icon - * @param inst the instance - * @param destination the destination path - */ - static inline void extractIcon(BaseInstance *inst, QString destination); - - /** - * @brief extract the MultiMC launcher.jar - * @param destination the destination path - */ - static inline void extractLauncher(QString destination); - - /** - * @brief prepare the launch by extracting icon and launcher - * @param inst the instance - */ - static void prepare(BaseInstance *inst); - + void setMinecraftWorkdir(QString path); + + void setMinecraftArguments(QStringList args); + signals: /** * @brief emitted when mc has finished and the PostLaunchCommand was run @@ -94,18 +76,13 @@ signals: protected: BaseInstance *m_instance; - QString m_user; - QString m_session; + QStringList m_args; QString m_err_leftover; QString m_out_leftover; QProcess m_prepostlaunchprocess; - QStringList m_arguments; - - void genArgs(); protected slots: void finish(int, QProcess::ExitStatus status); void on_stdErr(); void on_stdOut(); - }; diff --git a/backend/MinecraftVersion.cpp b/backend/MinecraftVersion.cpp index 6f3b1b86..d6e54404 100644 --- a/backend/MinecraftVersion.cpp +++ b/backend/MinecraftVersion.cpp @@ -51,9 +51,6 @@ QString MinecraftVersion::typeName() const case Snapshot: return "Snapshot"; - case MCNostalgia: - return "MCNostalgia"; - default: return QString("Unknown Type %1").arg(versionType()); } @@ -84,21 +81,10 @@ QString MinecraftVersion::etag() const return m_etag; } -MinecraftVersion::VersionSource MinecraftVersion::versionSource() const -{ - return m_versionSource; -}; - -void MinecraftVersion::setVersionSource(VersionSource launcherVersion) -{ - m_versionSource = launcherVersion; -} - InstVersion *MinecraftVersion::copyVersion(InstVersionList *newParent) const { MinecraftVersion *version = new MinecraftVersion( descriptor(), name(), timestamp(), downloadURL(), etag(), newParent); version->setVersionType(versionType()); - version->setVersionSource(VersionSource()); return version; } diff --git a/backend/MinecraftVersion.h b/backend/MinecraftVersion.h index a69b4710..98b10f2d 100644 --- a/backend/MinecraftVersion.h +++ b/backend/MinecraftVersion.h @@ -39,14 +39,6 @@ public: Stable, CurrentStable, Snapshot, - MCNostalgia - }; - - enum VersionSource - { - Unknown = -1, - Legacy = 0, // the legacy launcher that's been around since ... forever - Launcher16 = 1, // current launcher as of 26/06/2013 }; virtual QString descriptor() const; @@ -57,9 +49,6 @@ public: virtual VersionType versionType() const; virtual void setVersionType(VersionType typeName); - virtual VersionSource versionSource() const; - virtual void setVersionSource(VersionSource launcherVersion); - virtual QString downloadURL() const; virtual QString etag() const; @@ -74,7 +63,4 @@ private: /// This version's type. Used internally to identify what kind of version this is. VersionType m_type; - - /// Whete to get the full version info (or, where did we get this version from originally) - VersionSource m_versionSource; }; diff --git a/backend/OneSixInstance.cpp b/backend/OneSixInstance.cpp index e69de29b..1932651c 100644 --- a/backend/OneSixInstance.cpp +++ b/backend/OneSixInstance.cpp @@ -0,0 +1,18 @@ +#include "OneSixInstance.h" +#include "OneSixInstance_p.h" + +OneSixInstance::OneSixInstance ( const QString& rootDir, SettingsObject* settings, QObject* parent ) +: BaseInstance ( new OneSixInstancePrivate(), rootDir, settings, parent ) +{ + +} + +GameUpdateTask* OneSixInstance::doUpdate() +{ + return nullptr; +} + +MinecraftProcess* OneSixInstance::prepareForLaunch ( QString user, QString session ) +{ + return nullptr; +} diff --git a/backend/OneSixInstance.h b/backend/OneSixInstance.h index 7b9637ef..2abf5b49 100644 --- a/backend/OneSixInstance.h +++ b/backend/OneSixInstance.h @@ -1 +1,11 @@ -#pragma once \ No newline at end of file +#pragma once + +#include "BaseInstance.h" +class LIBMULTIMC_EXPORT OneSixInstance : public BaseInstance +{ + Q_OBJECT +public: + explicit OneSixInstance(const QString &rootDir, SettingsObject * settings, QObject *parent = 0); + virtual GameUpdateTask* doUpdate(); + virtual MinecraftProcess* prepareForLaunch ( QString user, QString session ); +}; \ No newline at end of file diff --git a/backend/OneSixInstance_p.h b/backend/OneSixInstance_p.h new file mode 100644 index 00000000..5bd60155 --- /dev/null +++ b/backend/OneSixInstance_p.h @@ -0,0 +1,8 @@ +#pragma once +#include +#include +#include "BaseInstance_p.h" + +struct OneSixInstancePrivate: public BaseInstancePrivate +{ +}; \ No newline at end of file diff --git a/backend/lists/MinecraftVersionList.cpp b/backend/lists/MinecraftVersionList.cpp index d576397f..feb479a9 100644 --- a/backend/lists/MinecraftVersionList.cpp +++ b/backend/lists/MinecraftVersionList.cpp @@ -181,14 +181,6 @@ void MCVListLoadTask::executeTask() { qDebug() << "Failed to load from Mojang version list."; } - if (!loadFromAssets()) - { - qDebug() << "Failed to load assets version list."; - } - if (!loadMCNostalgia()) - { - qDebug() << "Failed to load MCNostalgia version list."; - } finalize(); } @@ -295,7 +287,6 @@ bool MCVListLoadTask::loadFromVList() MinecraftVersion *mcVersion = new MinecraftVersion( versionID, versionID, versionTime.toMSecsSinceEpoch(), dlUrl, ""); - mcVersion->setVersionSource(MinecraftVersion::Launcher16); mcVersion->setVersionType(versionType); tempList.append(mcVersion); } @@ -317,143 +308,6 @@ bool MCVListLoadTask::loadFromVList() return true; } -bool MCVListLoadTask::loadFromAssets() -{ - setSubStatus("Loading versions from assets.minecraft.net..."); - - bool succeeded = false; - - QNetworkReply *assetsReply = netMgr->get(QNetworkRequest(QUrl(ASSETS_URLBASE))); - NetUtils::waitForNetRequest(assetsReply); - - switch (assetsReply->error()) - { - case QNetworkReply::NoError: - { - // Get the XML string. - QString xmlString = assetsReply->readAll(); - - QString xmlErrorMsg; - - QDomDocument doc; - if (!doc.setContent(xmlString, false, &xmlErrorMsg)) - { - // TODO: Display error message to the user. - qDebug() << "Failed to process assets.minecraft.net. XML error:" << - xmlErrorMsg << xmlString; - } - - QDomNodeList contents = doc.elementsByTagName("Contents"); - - QRegExp mcRegex("/minecraft.jar$"); - QRegExp snapshotRegex("[0-9][0-9]w[0-9][0-9][a-z]?|pre|rc"); - - for (int i = 0; i < contents.length(); i++) - { - QDomElement element = contents.at(i).toElement(); - - if (element.isNull()) - continue; - - QDomElement keyElement = getDomElementByTagName(element, "Key"); - QDomElement lastmodElement = getDomElementByTagName(element, "LastModified"); - QDomElement etagElement = getDomElementByTagName(element, "ETag"); - - if (keyElement.isNull() || lastmodElement.isNull() || etagElement.isNull()) - continue; - - QString key = keyElement.text(); - QString lastModStr = lastmodElement.text(); - QString etagStr = etagElement.text(); - - if (!key.contains(mcRegex)) - continue; - - QString versionDirName = key.left(key.length() - 14); - QString dlUrl = QString("http://assets.minecraft.net/%1/").arg(versionDirName); - - QString versionName = versionDirName.replace("_", "."); - - QDateTime versionTimestamp = timeFromS3Time(lastModStr); - if (!versionTimestamp.isValid()) - { - qDebug(QString("Failed to parse timestamp for version %1 %2"). - arg(versionName, lastModStr).toUtf8()); - versionTimestamp = QDateTime::currentDateTime(); - } - - if (m_currentStable) - { - { - bool older = versionTimestamp.toMSecsSinceEpoch() < m_currentStable->timestamp(); - bool newer = versionTimestamp.toMSecsSinceEpoch() > m_currentStable->timestamp(); - bool isSnapshot = versionName.contains(snapshotRegex); - - MinecraftVersion *version = new MinecraftVersion( - versionName, versionName, - versionTimestamp.toMSecsSinceEpoch(), - dlUrl, etagStr); - - if (newer) - { - version->setVersionType(MinecraftVersion::Snapshot); - } - else if (older && isSnapshot) - { - version->setVersionType(MinecraftVersion::OldSnapshot); - } - else if (older) - { - version->setVersionType(MinecraftVersion::Stable); - } - else - { - // Shouldn't happen, but just in case... - version->setVersionType(MinecraftVersion::CurrentStable); - } - - assetsList.push_back(version); - } - } - else // If there isn't a current stable version. - { - bool isSnapshot = versionName.contains(snapshotRegex); - - MinecraftVersion *version = new MinecraftVersion( - versionName, versionName, - versionTimestamp.toMSecsSinceEpoch(), - dlUrl, etagStr); - version->setVersionType(isSnapshot? MinecraftVersion::Snapshot : - MinecraftVersion::Stable); - assetsList.push_back(version); - } - } - - setSubStatus("Loaded assets.minecraft.net"); - succeeded = true; - break; - } - - default: - // TODO: Network error handling. - qDebug() << "Failed to load assets.minecraft.net" << assetsReply->errorString(); - break; - } - - processedAssetsReply = true; - updateStuff(); - return succeeded; -} - -bool MCVListLoadTask::loadMCNostalgia() -{ - QNetworkReply *mcnReply = netMgr->get(QNetworkRequest(QUrl(QString(MCN_URLBASE) + "?pversion=1&list=True"))); - NetUtils::waitForNetRequest(mcnReply); - processedMCNReply = true; - updateStuff(); - return true; -} - bool MCVListLoadTask::finalize() { // First, we need to do some cleanup. We loaded assets versions into assetsList, @@ -509,15 +363,11 @@ bool MCVListLoadTask::finalize() void MCVListLoadTask::updateStuff() { - const int totalReqs = 3; + const int totalReqs = 1; int reqsComplete = 0; if (processedMCVListReply) reqsComplete++; - if (processedAssetsReply) - reqsComplete++; - if (processedMCNReply) - reqsComplete++; calcProgress(reqsComplete, totalReqs); diff --git a/backend/lists/MinecraftVersionList.h b/backend/lists/MinecraftVersionList.h index 10570b01..8da74112 100644 --- a/backend/lists/MinecraftVersionList.h +++ b/backend/lists/MinecraftVersionList.h @@ -79,12 +79,6 @@ protected: //! Loads versions from Mojang's official version list. bool loadFromVList(); - //! Loads versions from assets.minecraft.net. Any duplicates are ignored. - bool loadFromAssets(); - - //! Loads versions from MCNostalgia. - bool loadMCNostalgia(); - //! Finalizes loading by updating the version list. bool finalize(); diff --git a/backend/tasks/GameUpdateTask.cpp b/backend/tasks/GameUpdateTask.cpp index 0a1df0e1..2b1acf26 100644 --- a/backend/tasks/GameUpdateTask.cpp +++ b/backend/tasks/GameUpdateTask.cpp @@ -43,8 +43,8 @@ void GameUpdateTask::executeTask() updateStatus(); // Get a pointer to the version object that corresponds to the instance's version. - targetVersion = (MinecraftVersion *)MinecraftVersionList::getMainList(). - findVersion(m_inst->intendedVersion()); + //FIXME: HACKERY + // targetVersion = (MinecraftVersion *)MinecraftVersionList::getMainList().findVersion(m_inst->intendedVersion()); if(targetVersion == NULL) { //Q_ASSERT_X(targetVersion != NULL, "game update", "instance's intended version is not an actual version"); @@ -60,20 +60,6 @@ void GameUpdateTask::executeTask() setState(StateDetermineURLs); - if (targetVersion->versionSource() == MinecraftVersion::Launcher16) - { - determineNewVersion(); - } - else - { - getLegacyJar(); - } - QEventLoop loop; - loop.exec(); -} - -void GameUpdateTask::determineNewVersion() -{ QString urlstr("http://s3.amazonaws.com/Minecraft.Download/versions/"); urlstr += targetVersion->descriptor() + "/" + targetVersion->descriptor() + ".json"; auto dljob = DownloadJob::create(QUrl(urlstr)); @@ -83,6 +69,9 @@ void GameUpdateTask::determineNewVersion() connect(specificVersionDownloadJob.data(), SIGNAL(failed()), SLOT(versionFileFailed())); connect(specificVersionDownloadJob.data(), SIGNAL(progress(qint64,qint64)), SLOT(updateDownloadProgress(qint64,qint64))); download_queue.enqueue(specificVersionDownloadJob); + + QEventLoop loop; + loop.exec(); } void GameUpdateTask::versionFileFinished() @@ -98,15 +87,8 @@ void GameUpdateTask::versionFileFinished() exit(0); } - if(version->isLegacy) - { - getLegacyJar(); - return; - } - // save the version file in $instanceId/version.json and versions/$version/$version.json QString version_id = targetVersion->descriptor(); - QString mc_dir = m_inst->minecraftDir(); QString inst_dir = m_inst->rootDir(); QString version1 = PathCombine(inst_dir, "/version.json"); QString version2 = QString("versions/") + version_id + "/" + version_id + ".json"; @@ -139,8 +121,9 @@ void GameUpdateTask::versionFileFinished() void GameUpdateTask::jarlibFinished() { - m_inst->setCurrentVersion(targetVersion->descriptor()); - m_inst->setShouldUpdate(false); + //FIXME: HACKERY + // m_inst->setCurrentVersion(targetVersion->descriptor()); + // m_inst->setShouldUpdate(false); // m_inst->setIsForNewLauncher(true); exit(1); } @@ -158,54 +141,6 @@ void GameUpdateTask::versionFileFailed() } -// this is legacy minecraft... -void GameUpdateTask::getLegacyJar() -{ - // Make directories - QDir binDir(m_inst->binDir()); - if (!binDir.exists() && !binDir.mkpath(".")) - { - error("Failed to create bin folder."); - return; - } - - // Add the URL for minecraft.jar - // This will be either 'minecraft' or the version number, depending on where - // we're downloading from. - QString jarFilename = "minecraft"; - if (targetVersion->versionSource() == MinecraftVersion::Launcher16) - { - jarFilename = targetVersion->descriptor(); - } - - QUrl mcJarURL = targetVersion->downloadURL() + jarFilename + ".jar"; - qDebug() << mcJarURL.toString(); - auto dljob = DownloadJob::create(mcJarURL, PathCombine(m_inst->minecraftDir(), "bin/minecraft.jar")); - - legacyDownloadJob.reset(new JobList()); - legacyDownloadJob->add(dljob); - connect(legacyDownloadJob.data(), SIGNAL(finished()), SLOT(legacyJarFinished())); - connect(legacyDownloadJob.data(), SIGNAL(failed()), SLOT(legacyJarFailed())); - connect(legacyDownloadJob.data(), SIGNAL(progress(qint64,qint64)), SLOT(updateDownloadProgress(qint64,qint64))); - - download_queue.enqueue(legacyDownloadJob); -} - - -void GameUpdateTask::legacyJarFinished() -{ - setState(StateFinished); - emit gameUpdateComplete(m_response); - // m_inst->setIsForNewLauncher(true); - exit(1); -} - -void GameUpdateTask::legacyJarFailed() -{ - emit gameUpdateError("failed to download the minecraft.jar"); - exit(0); -} - int GameUpdateTask::state() const { return m_updateState; diff --git a/backend/tasks/GameUpdateTask.h b/backend/tasks/GameUpdateTask.h index 94e798f1..ea0cf658 100644 --- a/backend/tasks/GameUpdateTask.h +++ b/backend/tasks/GameUpdateTask.h @@ -91,8 +91,6 @@ public slots: private slots: void updateDownloadProgress(qint64 current, qint64 total); - void legacyJarFinished(); - void legacyJarFailed(); void versionFileFinished(); void versionFileFailed(); diff --git a/gui/instancemodel.cpp b/gui/instancemodel.cpp index 6f130fd5..5d47ed2d 100644 --- a/gui/instancemodel.cpp +++ b/gui/instancemodel.cpp @@ -1,5 +1,5 @@ #include "instancemodel.h" -#include +#include #include #include "iconcache.h" diff --git a/gui/instancesettings.cpp b/gui/instancesettings.cpp index eea61ce8..36ff2c20 100644 --- a/gui/instancesettings.cpp +++ b/gui/instancesettings.cpp @@ -72,14 +72,12 @@ void InstanceSettings::applySettings() m_obj->set("OverrideWindow", window); if(window) { - m_obj->set("LaunchCompatMode", ui->compatModeCheckBox->isChecked()); m_obj->set("LaunchMaximized", ui->maximizedCheckBox->isChecked()); m_obj->set("MinecraftWinWidth", ui->windowWidthSpinBox->value()); m_obj->set("MinecraftWinHeight", ui->windowHeightSpinBox->value()); } else { - m_obj->reset("LaunchCompatMode"); m_obj->reset("LaunchMaximized"); m_obj->reset("MinecraftWinWidth"); m_obj->reset("MinecraftWinHeight"); @@ -148,33 +146,33 @@ void InstanceSettings::applySettings() void InstanceSettings::loadSettings() { // Console + ui->consoleSettingsBox->setChecked(m_obj->get("OverrideConsole").toBool()); ui->showConsoleCheck->setChecked(m_obj->get("ShowConsole").toBool()); ui->autoCloseConsoleCheck->setChecked(m_obj->get("AutoCloseConsole").toBool()); - ui->consoleSettingsBox->setChecked(m_obj->get("OverrideConsole").toBool()); // Window Size - ui->compatModeCheckBox->setChecked(m_obj->get("LaunchCompatMode").toBool()); + ui->windowSizeGroupBox->setChecked(m_obj->get("OverrideWindow").toBool()); ui->maximizedCheckBox->setChecked(m_obj->get("LaunchMaximized").toBool()); ui->windowWidthSpinBox->setValue(m_obj->get("MinecraftWinWidth").toInt()); ui->windowHeightSpinBox->setValue(m_obj->get("MinecraftWinHeight").toInt()); - ui->windowSizeGroupBox->setChecked(m_obj->get("OverrideWindow").toBool()); + // Auto Login - ui->autoLoginChecBox->setChecked(m_obj->get("AutoLogin").toBool()); ui->accountSettingsGroupBox->setChecked(m_obj->get("OverrideLogin").toBool()); + ui->autoLoginChecBox->setChecked(m_obj->get("AutoLogin").toBool()); // Memory + ui->memoryGroupBox->setChecked(m_obj->get("OverrideMemory").toBool()); ui->minMemSpinBox->setValue(m_obj->get("MinMemAlloc").toInt()); ui->maxMemSpinBox->setValue(m_obj->get("MaxMemAlloc").toInt()); - ui->memoryGroupBox->setChecked(m_obj->get("OverrideMemory").toBool()); // Java Settings + ui->javaSettingsGroupBox->setChecked(m_obj->get("OverrideJava").toBool()); ui->javaPathTextBox->setText(m_obj->get("JavaPath").toString()); ui->jvmArgsTextBox->setText(m_obj->get("JvmArgs").toString()); - ui->javaSettingsGroupBox->setChecked(m_obj->get("OverrideJava").toBool()); // Custom Commands + ui->customCommandsGroupBox->setChecked(m_obj->get("OverrideCommands").toBool()); ui->preLaunchCmdTextBox->setText(m_obj->get("PreLaunchCommand").toString()); ui->postExitCmdTextBox->setText(m_obj->get("PostExitCommand").toString()); - ui->customCommandsGroupBox->setChecked(m_obj->get("OverrideCommands").toBool()); } diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index c403ea25..db3a2828 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -125,7 +125,7 @@ MainWindow::MainWindow ( QWidget *parent ) : view->setFrameShape ( QFrame::NoFrame ); ui->horizontalLayout->addWidget ( view ); - setWindowTitle ( QString ( "MultiMC %1" ).arg ( Version::current.toString() ) ); + setWindowTitle ( QString ( "MultiMC %1" ).arg ( AppVersion::current.toString() ) ); // TODO: Make this work with the new settings system. // restoreGeometry(settings->getConfig().value("MainWindowGeometry", saveGeometry()).toByteArray()); // restoreState(settings->getConfig().value("MainWindowState", saveState()).toByteArray()); @@ -199,7 +199,8 @@ void MainWindow::on_actionAddInstance_triggered() { case InstanceFactory::NoCreateError: newInstance->setName(newInstDlg->instName()); - newInstance->setIntendedVersion(newInstDlg->selectedVersion()->descriptor()); + // FIXME:HACKERY + // newInstance->setIntendedVersion(newInstDlg->selectedVersion()->descriptor()); instList.add(InstancePtr(newInstance)); return; @@ -414,18 +415,18 @@ void MainWindow::doLogin(const QString& errorMsg) void MainWindow::onLoginComplete(LoginResponse response) { - Q_ASSERT_X(m_activeInst != NULL, "onLoginComplete", "no active instance is set"); + if(!m_activeInst) + return; - if (!m_activeInst->shouldUpdate()) + GameUpdateTask *updateTask = m_activeInst->doUpdate(); + if(!updateTask) { launchInstance(m_activeInst, response); } else { TaskDialog *tDialog = new TaskDialog(this); - GameUpdateTask *updateTask = new GameUpdateTask(response, m_activeInst); - connect(updateTask, SIGNAL(gameUpdateComplete(LoginResponse)), - SLOT(onGameUpdateComplete(LoginResponse))); + connect(updateTask, SIGNAL(gameUpdateComplete(LoginResponse)),SLOT(onGameUpdateComplete(LoginResponse))); connect(updateTask, SIGNAL(gameUpdateError(QString)), SLOT(onGameUpdateError(QString))); tDialog->exec(updateTask); } @@ -433,37 +434,24 @@ void MainWindow::onLoginComplete(LoginResponse response) void MainWindow::onGameUpdateComplete(LoginResponse response) { - launchInstance(response); + launchInstance(m_activeInst, response); } void MainWindow::onGameUpdateError(QString error) { - QMessageBox::warning(this, "Error downloading instance", error); -} - - -void MainWindow::launchInstance(LoginResponse response) -{ - Q_ASSERT_X(m_activeInst != NULL, "onLoginComplete", "no active instance is set"); - launchInstance(m_activeInst, response); -} - -void MainWindow::launchInstance(QString instID, LoginResponse response) -{ - BaseInstance *instance = instList.getInstanceById(instID).data(); - Q_ASSERT_X(instance != NULL, "launchInstance", "instance ID does not correspond to a valid instance"); - launchInstance(instance, response); + QMessageBox::warning(this, "Error updating instance", error); } void MainWindow::launchInstance(BaseInstance *instance, LoginResponse response) { Q_ASSERT_X(instance != NULL, "launchInstance", "instance is NULL"); - console = new ConsoleWindow(); - proc = new MinecraftProcess(instance, response.username(), response.sessionID()); + proc = instance->prepareForLaunch(response.username(), response.sessionID()); + if(!proc) + return; + console = new ConsoleWindow(); console->show(); - //connect(proc, SIGNAL(ended()), SLOT(onTerminated())); connect(proc, SIGNAL(log(QString, MessageLevel::Enum)), console, SLOT(write(QString, MessageLevel::Enum))); proc->launch(); @@ -536,7 +524,8 @@ void MainWindow::on_actionChangeInstMCVersion_triggered() VersionSelectDialog *vselect = new VersionSelectDialog(inst->versionList(), this); if (vselect->exec() && vselect->selectedVersion()) { - inst->setIntendedVersion(vselect->selectedVersion()->descriptor()); + // FIXME:HACKERY + // inst->setIntendedVersion(vselect->selectedVersion()->descriptor()); } } diff --git a/gui/mainwindow.h b/gui/mainwindow.h index 67ae859e..738dac0c 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -113,12 +113,10 @@ private slots: public slots: void instanceActivated ( QModelIndex ); - void instanceChanged ( QModelIndex ); + void instanceChanged ( QModelIndex ); void startTask(Task *task); - void launchInstance(LoginResponse response); - void launchInstance(QString instID, LoginResponse response); void launchInstance(BaseInstance *inst, LoginResponse response); private: diff --git a/gui/settingsdialog.cpp b/gui/settingsdialog.cpp index 52867169..d3be9cd3 100644 --- a/gui/settingsdialog.cpp +++ b/gui/settingsdialog.cpp @@ -122,7 +122,6 @@ void SettingsDialog::applySettings(SettingsObject *s) s->set("AutoCloseConsole", ui->autoCloseConsoleCheck->isChecked()); // Window Size - s->set("LaunchCompatMode", ui->compatModeCheckBox->isChecked()); s->set("LaunchMaximized", ui->maximizedCheckBox->isChecked()); s->set("MinecraftWinWidth", ui->windowWidthSpinBox->value()); s->set("MinecraftWinHeight", ui->windowHeightSpinBox->value()); @@ -159,7 +158,6 @@ void SettingsDialog::loadSettings(SettingsObject *s) ui->autoCloseConsoleCheck->setChecked(s->get("AutoCloseConsole").toBool()); // Window Size - ui->compatModeCheckBox->setChecked(s->get("LaunchCompatMode").toBool()); ui->maximizedCheckBox->setChecked(s->get("LaunchMaximized").toBool()); ui->windowWidthSpinBox->setValue(s->get("MinecraftWinWidth").toInt()); ui->windowHeightSpinBox->setValue(s->get("MinecraftWinHeight").toInt()); diff --git a/main.cpp b/main.cpp index f2217331..51cdde3f 100644 --- a/main.cpp +++ b/main.cpp @@ -64,13 +64,18 @@ private slots: void onLoginComplete(QString instId, LoginResponse response) { - // TODO: console + proc = instance->prepareForLaunch(response.username(), response.sessionID()); + if(!proc) + { + //FIXME: report error + return; + } console = new ConsoleWindow(); - proc = new MinecraftProcess(instance.data(), response.username(), response.sessionID()); - //if (instance->getShowConsole()) console->show(); + connect(proc, SIGNAL(ended()), SLOT(onTerminated())); connect(proc, SIGNAL(log(QString,MessageLevel::Enum)), console, SLOT(write(QString,MessageLevel::Enum))); + proc->launch(); }