diff --git a/CMakeLists.txt b/CMakeLists.txt index 1853a8f41..88e7e4d4c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,30 +1,47 @@ cmake_minimum_required(VERSION 2.8.9) project(MultiMC) -set(CMAKE_AUTOMOC ON) -set(CMAKE_INCLUDE_CURRENT_DIR ON) +######## Set CMake options ######## +SET(CMAKE_AUTOMOC ON) +SET(CMAKE_INCLUDE_CURRENT_DIR ON) +# Output all executables and shared libs in the main build folder, not in subfolders. +SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) -#### Check for machine endianness #### -INCLUDE(TestBigEndian) -TEST_BIG_ENDIAN(BIGENDIAN) -IF(${BIGENDIAN}) - ADD_DEFINITIONS(-DMULTIMC_BIG_ENDIAN) -ENDIF(${BIGENDIAN}) +######## Set compiler flags ######## +IF(APPLE) + # assume clang 4.1.0+, add C++0x/C++11 stuff + message(STATUS "Using APPLE CMAKE_CXX_FLAGS") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -stdlib=libc++") +ELSEIF(UNIX) + # assume GCC, add C++0x/C++11 stuff + MESSAGE(STATUS "Using UNIX CMAKE_CXX_FLAGS") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") +ELSEIF(MINGW) + MESSAGE(STATUS "Using MINGW CMAKE_CXX_FLAGS") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x") +ENDIF() + +################################ INCLUDE LIBRARIES ################################ # First, include header overrides include_directories(hacks) -#### Find the required Qt parts #### -find_package(Qt5Widgets) -find_package(Qt5Network) -#find_package(Qt5Declarative) + +######## 3rd Party Libs ######## + +# Find the required Qt parts +find_package(Qt5Widgets REQUIRED) +find_package(Qt5Network REQUIRED) include_directories(${Qt5Widgets_INCLUDE_DIRS}) -# find ZLIB for quazip +# Find ZLIB for quazip find_package(ZLIB REQUIRED) + +######## Included Libs ######## + # Add quazip add_subdirectory(quazip) @@ -32,101 +49,108 @@ add_subdirectory(quazip) add_subdirectory(patchlib) include_directories(patchlib) -# add the java launcher +# Add the java launcher add_subdirectory(launcher) -IF(APPLE) - # assume clang 4.1.0+, add C++0x/C++11 stuff - message(STATUS "Using APPLE CMAKE_CXX_FLAGS") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -stdlib=libc++") -ELSEIF(UNIX) - # assume GCC, add C++0x/C++11 stuff - message(STATUS "Using UNIX CMAKE_CXX_FLAGS") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") -ELSEIF(MINGW) - message(STATUS "Using MINGW CMAKE_CXX_FLAGS") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x") -ENDIF() -# Set the path where CMake will look for modules. -set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}") +######## MultiMC Libs ######## + +# Add the util library. +add_subdirectory(libutil) +include_directories(${LIBMMCUTIL_INCLUDE_DIR}) + +# Add the settings library. +add_subdirectory(libsettings) +include_directories(${LIBMMCSETTINGS_INCLUDE_DIR}) + +# Add the instance library. +add_subdirectory(libinstance) +include_directories(${LIBMMCINST_INCLUDE_DIR}) + +# Add the stdinstance plugin. +add_subdirectory(plugins/stdinstance) -set(MultiMC_VERSION_MAJOR 5) -set(MultiMC_VERSION_MINOR 0) -set(MultiMC_VERSION_REV 0) +################################ SET UP BUILD OPTIONS ################################ + +######## Check endianness ######## +INCLUDE(TestBigEndian) +TEST_BIG_ENDIAN(BIGENDIAN) +IF(${BIGENDIAN}) + ADD_DEFINITIONS(-DMULTIMC_BIG_ENDIAN) +ENDIF(${BIGENDIAN}) + + +######## Set module path ######## +SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}") + + +######## Set version numbers ######## +SET(MultiMC_VERSION_MAJOR 5) +SET(MultiMC_VERSION_MINOR 0) +SET(MultiMC_VERSION_REV 0) + +# Jenkins build number SET(MultiMC_VERSION_BUILD 0 CACHE STRING "Build number.") -message(STATUS "MultiMC build #${MultiMC_VERSION_BUILD}") +MESSAGE(STATUS "MultiMC build #${MultiMC_VERSION_BUILD}") -IF (DEFINED MultiMC_BUILD_TAG) - message(STATUS "Build tag: ${MultiMC_BUILD_TAG}") -ELSE () - message(STATUS "No build tag specified.") -ENDIF () +# Check the current Git commit +execute_process(COMMAND git rev-parse HEAD + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + RESULT_VARIABLE GIT_COMMIT_CHECK_RESULTVAR + OUTPUT_VARIABLE GIT_COMMIT_CHECK_OUTVAR + OUTPUT_STRIP_TRAILING_WHITESPACE +) -if( CMAKE_SIZEOF_VOID_P EQUAL 8 ) - set (MultiMC_ARCH "x64" - CACHE STRING "Architecture we're building for.") -else() - set (MultiMC_ARCH "x86" - CACHE STRING "Architecture we're building for.") -endif() -message (STATUS "Architecture is ${MultiMC_ARCH}") - -SET(MultiMC_Extra_Label "") - -IF (WIN32) - SET(MultiMC_JOB_NAME "MultiMC4Windows" CACHE STRING "Jenkins job name.") -ELSEIF(UNIX AND APPLE) - SET(MultiMC_JOB_NAME "MultiMC4OSX" CACHE STRING "Jenkins job name.") - # This is here because the scheme doesn't exactly apply to every kind of build... - SET(MultiMC_Extra_Label ",label=osx") +# If Git executed successfully +IF(GIT_COMMIT_CHECK_RESULTVAR EQUAL 0) + SET(MultiMC_GIT_COMMIT "${GIT_COMMIT_CHECK_OUTVAR}") + MESSAGE(STATUS "Git commit: ${MultiMC_GIT_COMMIT}") ELSE() - SET(MultiMC_JOB_NAME "MultiMC4Linux" CACHE STRING "Jenkins job name.") + SET(MultiMC_GIT_COMMIT "Unknown") + MESSAGE(STATUS "Failed to check Git commit. ${GIT_COMMIT_CHECK_RESULTVAR}") ENDIF() + +######## Set Jenkins info ######## +# Jenkins build tag +IF(DEFINED MultiMC_BUILD_TAG) + MESSAGE(STATUS "Build tag: ${MultiMC_BUILD_TAG}") +ELSE() + MESSAGE(STATUS "No build tag specified.") +ENDIF() + +# Architecture detection +IF(CMAKE_SIZEOF_VOID_P EQUAL 8) + SET(MultiMC_ARCH "x64" CACHE STRING "Architecture we're building for.") +ELSE() + SET(MultiMC_ARCH "x86" CACHE STRING "Architecture we're building for.") +ENDIF() +MESSAGE(STATUS "Architecture is ${MultiMC_ARCH}") + +# Jenkins job name +IF(WIN32) + SET(MultiMC_JOB_NAME "MultiMC5Windows" CACHE STRING "Jenkins job name.") +ELSEIF(UNIX AND APPLE) + SET(MultiMC_JOB_NAME "MultiMC5OSX" CACHE STRING "Jenkins job name.") +ELSE() + SET(MultiMC_JOB_NAME "MultiMC5Linux" CACHE STRING "Jenkins job name.") +ENDIF() + +# Jenkins URL SET(MultiMC_JOB_URL "http://ci.forkk.net/job/${MultiMC_JOB_NAME}/arch=${MultiMC_ARCH}${MultiMC_Extra_Label}/" CACHE STRING "URL of the jenkins job to pull updates from.") -message(STATUS "Job URL: ${MultiMC_JOB_URL}") +MESSAGE(STATUS "Job URL: ${MultiMC_JOB_URL}") +######## Configure header ######## configure_file("${PROJECT_SOURCE_DIR}/config.h.in" "${PROJECT_BINARY_DIR}/config.h") -SET(MULTIMC_SOURCES -main.cpp - -data/appsettings.cpp -data/inifile.cpp -data/instancebase.cpp -data/instancemodel.cpp -data/stdinstance.cpp -data/version.cpp -data/userinfo.cpp -data/loginresponse.cpp - -gui/mainwindow.cpp -gui/modeditwindow.cpp -gui/settingsdialog.cpp -gui/newinstancedialog.cpp -gui/logindialog.cpp -gui/taskdialog.cpp -gui/browserdialog.cpp -gui/aboutdialog.cpp - -util/pathutils.cpp -util/osutils.cpp -util/userutil.cpp -util/cmdutils.cpp - -java/javautils.cpp -java/annotations.cpp - -tasks/task.cpp -tasks/logintask.cpp -) +################################ FILES ################################ +######## Headers ######## SET(MULTIMC_HEADERS gui/mainwindow.h gui/modeditwindow.h @@ -137,29 +161,18 @@ gui/taskdialog.h gui/browserdialog.h gui/aboutdialog.h -data/appsettings.h -data/inifile.h -data/instancebase.h -data/instancemodel.h -data/stdinstance.h data/version.h data/userinfo.h data/loginresponse.h -data/siglist.h -data/siglist_imp.h -util/apputils.h -util/pathutils.h -util/osutils.h -util/userutil.h -util/cmdutils.h +data/plugin/pluginmanager.h multimc_pragma.h java/annotations.h java/classfile.h java/constants.h -java/endian.h +java/javaendian.h java/errors.h java/javautils.h java/membuffer.h @@ -168,7 +181,36 @@ tasks/task.h tasks/logintask.h ) -SET(MULTIMC5_UIS + +######## Sources ######## +SET(MULTIMC_SOURCES +main.cpp + +data/version.cpp +data/userinfo.cpp +data/loginresponse.cpp + +data/plugin/pluginmanager.cpp + +gui/mainwindow.cpp +gui/modeditwindow.cpp +gui/settingsdialog.cpp +gui/newinstancedialog.cpp +gui/logindialog.cpp +gui/taskdialog.cpp +gui/browserdialog.cpp +gui/aboutdialog.cpp + +java/javautils.cpp +java/annotations.cpp + +tasks/task.cpp +tasks/logintask.cpp +) + + +######## UIs ######## +SET(MULTIMC_UIS gui/mainwindow.ui gui/modeditwindow.ui gui/settingsdialog.ui @@ -179,52 +221,62 @@ gui/browserdialog.ui gui/aboutdialog.ui ) -################################ Install ################################ -################ ICNS File ################ +######## Windows resource files ######## +IF(WIN32) +SET(MULTIMC_RCS multimc.rc) +ENDIF() + +################################ COMPILE ################################ + +# ICNS file for OS X IF(APPLE) SET(MACOSX_BUNDLE_ICON_FILE MultiMC.icns) SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/MultiMC.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources) SET(MULTIMC_SOURCES ${MULTIMC_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/MultiMC.icns) ENDIF(APPLE) - -################ Build ################ - -IF (WIN32) +# Link additional libraries +IF(WIN32) SET(MultiMC_LINK_ADDITIONAL_LIBS ${MultiMC_LINK_ADDITIONAL_LIBS} - Qt5::WinMain + Qt5::WinMain # Link WinMain ) -ENDIF (WIN32) +ENDIF(WIN32) +# Tell CMake that MultiMCLauncher.jar is generated. SET_SOURCE_FILES_PROPERTIES(resources/MultiMCLauncher.jar GENERATED) -QT5_WRAP_UI(MULTIMC_UI ${MULTIMC5_UIS}) +# Qt 5 stuff +QT5_WRAP_UI(MULTIMC_UI ${MULTIMC_UIS}) QT5_ADD_RESOURCES(MULTIMC_QRC multimc.qrc) -add_executable(MultiMC MACOSX_BUNDLE WIN32 ${MULTIMC_SOURCES} ${MULTIMC_HEADERS} ${MULTIMC_UI} ${MULTIMC_QRC}) -qt5_use_modules(MultiMC Widgets Network WebKitWidgets) -target_link_libraries(MultiMC quazip patchlib ${MultiMC_LINK_ADDITIONAL_LIBS}) -add_dependencies(MultiMC MultiMCLauncher) +# Add executable +ADD_EXECUTABLE(MultiMC MACOSX_BUNDLE WIN32 + ${MULTIMC_SOURCES} ${MULTIMC_HEADERS} ${MULTIMC_UI} ${MULTIMC_QRC} ${MULTIMC_RCS}) -IF (WIN32) -install(TARGETS MultiMC RUNTIME DESTINATION .) -ELSE() -install(TARGETS MultiMC RUNTIME DESTINATION bin) -ENDIF() +# Link +QT5_USE_MODULES(MultiMC Widgets Network WebKitWidgets) +TARGET_LINK_LIBRARIES(MultiMC quazip patchlib +libmmcutil libmmcsettings libmmcinst +${MultiMC_LINK_ADDITIONAL_LIBS}) +ADD_DEPENDENCIES(MultiMC MultiMCLauncher libmmcutil libmmcsettings libmmcinst) -################ Dirs ################ + +################################ INSTALLATION AND PACKAGING ################################ + +######## Plugin and library folders ######## SET(PLUGIN_DEST_DIR bin) SET(QTCONF_DEST_DIR bin) SET(APPS "\${CMAKE_INSTALL_PREFIX}/bin/MultiMC") IF(WIN32) - #SET(PLUGIN_DEST_DIR .) - #SET(QTCONF_DEST_DIR .) - SET(APPS "\${CMAKE_INSTALL_PREFIX}/bin/MultiMC.exe") + SET(PLUGIN_DEST_DIR .) + SET(QTCONF_DEST_DIR .) + SET(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.exe") ENDIF() + IF(APPLE) SET(PLUGIN_DEST_DIR MultiMC.app/Contents/MacOS) SET(QTCONF_DEST_DIR MultiMC.app/Contents/Resources) @@ -235,23 +287,24 @@ SET(QT_PLUGINS_DIR ${Qt5_DIR}/plugins) SET(QT_LIBRARY_DIRS ${Qt5_DIR}/lib) -################ OS X Bundle Info ################ +######## OS X Bundle Info ######## IF(APPLE) SET(MACOSX_BUNDLE_BUNDLE_NAME "MultiMC") SET(MACOSX_BUNDLE_INFO_STRING "MultiMC Minecraft launcher and management utility.") - SET(MACOSX_BUNDLE_BUNDLE_VERSION "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}") + SET(MACOSX_BUNDLE_BUNDLE_VERSION + "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_REV}.${MultiMC_VERSION_BUILD}") #SET(MACOSX_BUNDLE_GUI_IDENTIFIER "") SET(MACOSX_BUNDLE_ICON_FILE MultiMC.icns) ENDIF(APPLE) -################ Install ################ +######## Install ######## -# Executable +#### Executable #### IF(WIN32) INSTALL(TARGETS MultiMC BUNDLE DESTINATION . COMPONENT Runtime - RUNTIME DESTINATION bin COMPONENT Runtime + RUNTIME DESTINATION . COMPONENT Runtime ) ENDIF() IF(UNIX) @@ -268,7 +321,8 @@ INSTALL(TARGETS MultiMC ENDIF() ENDIF() -# Plugins + +#### Plugins #### # Image formats INSTALL(DIRECTORY "${QT_PLUGINS_DIR}/imageformats" DESTINATION ${PLUGIN_DEST_DIR} COMPONENT Runtime) @@ -283,7 +337,11 @@ INSTALL(CODE " # Dirs to look for dependencies. -SET(DIRS ${QT_LIBRARY_DIRS}) +SET(DIRS "${QT_LIBRARY_DIRS} +${CMAKE_BINARY_DIR}/libutil +${CMAKE_BINARY_DIR}/libsettings +${CMAKE_BINARY_DIR}/libinstance") +message(STATUS "${DIRS}") INSTALL(CODE " file(GLOB_RECURSE QTPLUGINS @@ -293,16 +351,7 @@ INSTALL(CODE " " COMPONENT Runtime) -#GET_TARGET_PROPERTY(BINARY_LOCATION MultiMC LOCATION) -#CONFIGURE_FILE( -# "${CMAKE_CURRENT_SOURCE_DIR}/dependencies.cmake.in" -# "${CMAKE_CURRENT_BINARY_DIR}/dependencies.cmake" -# @ONLY -# ) -#INSTALL(SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/dependencies.cmake") - - -################ Package ################ +######## Package ######## # Package with CPack IF(UNIX) diff --git a/config.h.in b/config.h.in index de53ac935..fbc5aed26 100644 --- a/config.h.in +++ b/config.h.in @@ -3,6 +3,8 @@ #define VERSION_REVISION @MultiMC_VERSION_REV@ #define VERSION_BUILD @MultiMC_VERSION_BUILD@ +#define GIT_COMMIT "@MultiMC_GIT_COMMIT@" + #define VERSION_STR "@MultiMC_VERSION_MAJOR@.@MultiMC_VERSION_MINOR@.@MultiMC_VERSION_REV@.@MultiMC_VERSION_BUILD@" #define x86 1 diff --git a/data/instancebase.cpp b/data/instancebase.cpp deleted file mode 100644 index a5ef35a24..000000000 --- a/data/instancebase.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* 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 "instancebase.h" - -#include -#include - -#include "../util/pathutils.h" - -InstanceBase::InstanceBase(QString dir, QObject *parent) : - QObject(parent), - rootDir(dir) -{ - QFileInfo cfgFile(PathCombine(rootDir, "instance.cfg")); - - if (cfgFile.exists()) - { - if(!config.loadFile(cfgFile.absoluteFilePath())) - { - QString debugmsg("Can't load instance config file for instance "); - debugmsg+= getInstID(); - qDebug(debugmsg.toLocal8Bit()); - } - } - else - { - QString debugmsg("Can't find instance config file for instance "); - debugmsg+= getInstID(); - debugmsg += " : "; - debugmsg += - debugmsg+=" ... is this an instance even?"; - qDebug(debugmsg.toLocal8Bit()); - } - currentGroup = nullptr; -} - -QString InstanceBase::getRootDir() const -{ - return rootDir; -} - - -///////////// Config Values ///////////// - -// Name -QString InstanceBase::getInstName() const -{ - return config.get("name", "Unnamed").toString(); -} - -void InstanceBase::setInstName(QString name) -{ - config.set("name", name); -} - -QString InstanceBase::getInstID() const -{ - return QDir(rootDir).dirName(); -} - -InstanceModelItem* InstanceBase::getParent() const -{ - return currentGroup; -} - -QVariant InstanceBase::data ( int role ) const -{ - switch(role) - { - case Qt::DisplayRole: - return getInstName(); - default: - return QVariant(); - } -} -int InstanceBase::getRow() const -{ - return currentGroup->getIndexOf((InstanceBase*)this); -} - -InstanceModelItem* InstanceBase::getChild ( int index ) const -{ - return nullptr; -} -InstanceModel* InstanceBase::getModel() const -{ - return currentGroup->getModel(); -} -IMI_type InstanceBase::getModelItemType() const -{ - return IMI_Instance; -} -int InstanceBase::numChildren() const -{ - return 0; -} diff --git a/data/instancebase.h b/data/instancebase.h deleted file mode 100644 index fa043c5fb..000000000 --- a/data/instancebase.h +++ /dev/null @@ -1,58 +0,0 @@ -/* 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. - */ - -#ifndef INSTANCEBASE_H -#define INSTANCEBASE_H - -#include -#include - -#include "../data/inifile.h" -#include "instancemodel.h" - -class InstanceBase : public QObject, public InstanceModelItem -{ - friend class InstanceGroup; - Q_OBJECT -public: - explicit InstanceBase(QString rootDir, QObject *parent = 0); - - QString getRootDir() const; - - QString getInstName() const; - void setInstName(QString name); - - QString getInstID() const; - - virtual IMI_type getModelItemType() const; - virtual InstanceModelItem* getParent() const; - virtual int numChildren() const; - virtual InstanceModelItem* getChild ( int index ) const; - virtual InstanceModel* getModel() const; - virtual QVariant data ( int column ) const; - virtual int getRow() const; - -private: - void setGroup ( InstanceGroup* group ) - { - currentGroup = group; - }; - - QString rootDir; - INIFile config; - InstanceGroup * currentGroup; -}; - -#endif // INSTANCEBASE_H diff --git a/data/instancemodel.cpp b/data/instancemodel.cpp deleted file mode 100644 index fbdb82126..000000000 --- a/data/instancemodel.cpp +++ /dev/null @@ -1,457 +0,0 @@ -/* 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 "instancemodel.h" - -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include "data/stdinstance.h" -#include "util/pathutils.h" - -#define GROUP_FILE_FORMAT_VERSION 1 - -InstanceModel::InstanceModel( QObject* parent ) : - QAbstractItemModel() -{ -} - -InstanceModel::~InstanceModel() -{ - saveGroupInfo(); - for(int i = 0; i < groups.size(); i++) - { - delete groups[i]; - } -} - -void InstanceModel::addInstance( InstanceBase* inst, const QString& groupName ) -{ - auto group = getGroupByName(groupName); - group->addInstance(inst); -} - -void InstanceGroup::addInstance ( InstanceBase* inst ) -{ - instances.append(inst); - inst->setGroup(this); - // TODO: notify model. -} - - -void InstanceModel::initialLoad(QString dir) -{ - groupFileName = dir + "/instgroups.json"; - implicitGroup = new InstanceGroup("Ungrouped", this); - groups.append(implicitGroup); - - // temporary map from instance ID to group name - QMap groupMap; - - if (QFileInfo(groupFileName).exists()) - { - QFile groupFile(groupFileName); - - if (!groupFile.open(QIODevice::ReadOnly)) - { - // An error occurred. Ignore it. - qDebug("Failed to read instance group file."); - goto groupParseFail; - } - - QTextStream in(&groupFile); - QString jsonStr = in.readAll(); - groupFile.close(); - - QJsonParseError error; - QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonStr.toUtf8(), &error); - - if (error.error != QJsonParseError::NoError) - { - qWarning(QString("Failed to parse instance group file: %1 at offset %2"). - arg(error.errorString(), QString::number(error.offset)).toUtf8()); - goto groupParseFail; - } - - if (!jsonDoc.isObject()) - { - qWarning("Invalid group file. Root entry should be an object."); - goto groupParseFail; - } - - QJsonObject rootObj = jsonDoc.object(); - - // Make sure the format version matches. - if (rootObj.value("formatVersion").toVariant().toInt() == GROUP_FILE_FORMAT_VERSION) - { - // Get the group list. - if (!rootObj.value("groups").isObject()) - { - qWarning("Invalid group list JSON: 'groups' should be an object."); - goto groupParseFail; - } - - // Iterate through the list. - QJsonObject groupList = rootObj.value("groups").toObject(); - - for (QJsonObject::iterator iter = groupList.begin(); - iter != groupList.end(); iter++) - { - QString groupName = iter.key(); - - // If not an object, complain and skip to the next one. - if (!iter.value().isObject()) - { - qWarning(QString("Group '%1' in the group list should " - "be an object.").arg(groupName).toUtf8()); - continue; - } - - QJsonObject groupObj = iter.value().toObject(); - - // Create the group object. - InstanceGroup *group = new InstanceGroup(groupName, this); - groups.push_back(group); - - // If 'hidden' isn't a bool value, just assume it's false. - if (groupObj.value("hidden").isBool() && groupObj.value("hidden").toBool()) - { - group->setHidden(groupObj.value("hidden").toBool()); - } - - if (!groupObj.value("instances").isArray()) - { - qWarning(QString("Group '%1' in the group list is invalid. " - "It should contain an array " - "called 'instances'.").arg(groupName).toUtf8()); - continue; - } - - // Iterate through the list of instances in the group. - QJsonArray instancesArray = groupObj.value("instances").toArray(); - - for (QJsonArray::iterator iter2 = instancesArray.begin(); - iter2 != instancesArray.end(); iter2++) - { - groupMap[(*iter2).toString()] = groupName; - } - } - } - } - -groupParseFail: - - qDebug("Loading instances"); - QDir instDir(dir); - QDirIterator iter(instDir); - - while (iter.hasNext()) - { - QString subDir = iter.next(); - if (QFileInfo(PathCombine(subDir, "instance.cfg")).exists()) - { - // TODO Differentiate between different instance types. - InstanceBase* inst = new StdInstance(subDir); - QString instID = inst->getInstID(); - auto iter = groupMap.find(instID); - if(iter != groupMap.end()) - { - addInstance(inst,iter.value()); - } - else - { - addInstance(inst); - } - } - } -} - -int InstanceModel::columnCount ( const QModelIndex& parent ) const -{ - // for now... - return 1; -} - -QVariant InstanceModel::data ( const QModelIndex& index, int role ) const -{ - if (!index.isValid()) - return QVariant(); - - if (role != Qt::DisplayRole) - return QVariant(); - - InstanceModelItem *item = static_cast(index.internalPointer()); - - return item->data(index.column()); -} - -QModelIndex InstanceModel::index ( int row, int column, const QModelIndex& parent ) const -{ - if (!hasIndex(row, column, parent)) - return QModelIndex(); - - InstanceModelItem *parentItem; - - if (!parent.isValid()) - parentItem = (InstanceModelItem *) this; - else - parentItem = static_cast(parent.internalPointer()); - - InstanceModelItem *childItem = parentItem->getChild(row); - if (childItem) - return createIndex(row, column, childItem); - else - return QModelIndex(); - -} - -QModelIndex InstanceModel::parent ( const QModelIndex& index ) const -{ - if (!index.isValid()) - return QModelIndex(); - - InstanceModelItem *childItem = static_cast(index.internalPointer()); - InstanceModelItem *parentItem = childItem->getParent(); - - if (parentItem == this) - return QModelIndex(); - - return createIndex(parentItem->getRow(), 0, parentItem); -} - -int InstanceModel::rowCount ( const QModelIndex& parent ) const -{ - InstanceModelItem *parentItem; - if (parent.column() > 0) - return 0; - - if (!parent.isValid()) - parentItem = (InstanceModelItem*) this; - else - parentItem = static_cast(parent.internalPointer()); - - return parentItem->numChildren(); -} - -bool InstanceModel::saveGroupInfo() const -{ - /* - using namespace boost::property_tree; - ptree pt; - - pt.put("formatVersion", GROUP_FILE_FORMAT_VERSION); - - try - { - typedef QMap > GroupListMap; - - GroupListMap groupLists; - for (auto iter = instances.begin(); iter != instances.end(); iter++) - { - InstanceGroup *group = getInstanceGroup(*iter); - - if (group != nullptr) - groupLists[group].push_back(*iter); - } - - ptree groupsPtree; - for (auto iter = groupLists.begin(); iter != groupLists.end(); iter++) - { - auto group = iter.key(); - auto & gList = iter.value(); - - ptree groupTree; - - groupTree.put("hidden", group->isHidden()); - - ptree instList; - for (auto iter2 = gList.begin(); iter2 != gList.end(); iter2++) - { - std::string instID((*iter2)->getInstID().toUtf8()); - instList.push_back(std::make_pair("", ptree(instID))); - } - groupTree.put_child("instances", instList); - - groupsPtree.push_back(std::make_pair(std::string(group->getName().toUtf8()), groupTree)); - } - pt.put_child("groups", groupsPtree); - - write_json(groupFile.toStdString(), pt); - } - catch (json_parser_error e) - { -// wxLogError(_("Failed to read group list.\nJSON parser error at line %i: %s"), -// e.line(), wxStr(e.message()).c_str()); - return false; - } - catch (ptree_error e) - { -// wxLogError(_("Failed to save group list. Unknown ptree error.")); - return false; - } - - return true; - */ - return false; -} - -void InstanceModel::setInstanceGroup ( InstanceBase* inst, const QString& groupName ) -{ - /* - InstanceGroup *prevGroup = getInstanceGroup(inst); - - if (prevGroup != nullptr) - { - groupsMap.remove(inst); - } - - if (!groupName.isEmpty()) - { - InstanceGroup *newGroup = nullptr; - - for (auto iter = root->groups.begin(); iter != root->groups.end(); iter++) - { - if ((*iter)->getName() == groupName) - { - newGroup = *iter; - } - } - - if (newGroup == nullptr) - { - newGroup = new InstanceGroup(groupName, this); - root->groups.push_back(newGroup); - } - - groupsMap[inst] = newGroup; - } - - // TODO: propagate change, reflect in model, etc. - //InstanceGroupChanged(inst); - */ -} - -InstanceGroup* InstanceModel::getGroupByName ( const QString& name ) const -{ - for (auto iter = groups.begin(); iter != groups.end(); iter++) - { - if ((*iter)->getName() == name) - return *iter; - } - return nullptr; -} -/* -void InstanceModel::setGroupFile ( QString filename ) -{ - groupFile = filename; -}*/ - -int InstanceModel::numChildren() const -{ - return groups.count(); -} - -InstanceModelItem* InstanceModel::getChild ( int index ) const -{ - return groups[index]; -} - -QVariant InstanceModel::data ( int role ) const -{ - switch(role) - { - case Qt::DisplayRole: - return "name"; - } - return QVariant(); -} - - -InstanceGroup::InstanceGroup(const QString& name, InstanceModel *parent) -{ - this->name = name; - this->model = parent; - this->hidden = false; -} - -InstanceGroup::~InstanceGroup() -{ - for(int i = 0; i < instances.size(); i++) - { - delete instances[i]; - } -} - - -QString InstanceGroup::getName() const -{ - return name; -} - -void InstanceGroup::setName(const QString& name) -{ - this->name = name; - //TODO: propagate change -} - -InstanceModelItem* InstanceGroup::getParent() const -{ - return model; -} - -bool InstanceGroup::isHidden() const -{ - return hidden; -} - -void InstanceGroup::setHidden(bool hidden) -{ - this->hidden = hidden; - //TODO: propagate change -} - -int InstanceGroup::getRow() const -{ - return model->getIndexOf( this); -} - -InstanceModelItem* InstanceGroup::getChild ( int index ) const -{ - return instances[index]; -} - -int InstanceGroup::numChildren() const -{ - return instances.size(); -} - -QVariant InstanceGroup::data ( int role ) const -{ - switch(role) - { - case Qt::DisplayRole: - return name; - default: - return QVariant(); - } -} diff --git a/data/instancemodel.h b/data/instancemodel.h deleted file mode 100644 index 4bd348310..000000000 --- a/data/instancemodel.h +++ /dev/null @@ -1,137 +0,0 @@ -/* 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. - */ - -#ifndef INSTANCELIST_H -#define INSTANCELIST_H - -#include -#include -#include -#include - -enum IMI_type -{ - IMI_Root, - IMI_Group, - IMI_Instance -}; - -class InstanceModel; -class InstanceGroup; -class InstanceBase; - -class InstanceModelItem -{ - public: - virtual IMI_type getModelItemType() const = 0; - virtual InstanceModelItem * getParent() const = 0; - virtual int numChildren() const = 0; - virtual InstanceModelItem * getChild(int index) const = 0; - virtual InstanceModel * getModel() const = 0; - virtual QVariant data(int role) const = 0; - virtual int getRow() const = 0; -}; - -class InstanceGroup : public InstanceModelItem -{ -public: - InstanceGroup(const QString& name, InstanceModel * model); - ~InstanceGroup(); - - QString getName() const; - void setName(const QString& name); - - bool isHidden() const; - void setHidden(bool hidden); - - virtual IMI_type getModelItemType() const - { - return IMI_Group; - } - virtual InstanceModelItem* getParent() const; - virtual InstanceModelItem* getChild ( int index ) const; - virtual int numChildren() const; - virtual InstanceModel * getModel() const - { - return model; - }; - virtual QVariant data ( int column ) const; - int getIndexOf(InstanceBase * inst) - { - return instances.indexOf(inst); - }; - virtual int getRow() const; - void addInstance ( InstanceBase* inst ); -protected: - QString name; - InstanceModel * model; - QVector instances; - bool hidden; - int row; -}; - -class InstanceModel : public QAbstractItemModel, public InstanceModelItem -{ -public: - explicit InstanceModel(QObject *parent = 0); - ~InstanceModel(); - - virtual int columnCount ( const QModelIndex& parent = QModelIndex() ) const; - virtual QVariant data ( const QModelIndex& index, int role = Qt::DisplayRole ) const; - virtual QModelIndex index ( int row, int column, const QModelIndex& parent = QModelIndex() ) const; - virtual QModelIndex parent ( const QModelIndex& child ) const; - virtual int rowCount ( const QModelIndex& parent = QModelIndex() ) const; - - void addInstance(InstanceBase *inst, const QString& groupName = "Ungrouped"); - void setInstanceGroup(InstanceBase *inst, const QString & groupName); - InstanceGroup* getGroupByName(const QString & name) const; - - void initialLoad(QString dir); - bool saveGroupInfo() const; - - virtual IMI_type getModelItemType() const - { - return IMI_Root; - } - virtual InstanceModelItem * getParent() const - { - return nullptr; - }; - virtual int numChildren() const; - virtual InstanceModelItem* getChild ( int index ) const; - virtual InstanceModel* getModel() const - { - return nullptr; - }; - virtual QVariant data ( int column ) const; - int getIndexOf(const InstanceGroup * grp) const - { - return groups.indexOf((InstanceGroup *) grp); - }; - virtual int getRow() const - { - return 0; - }; -signals: - -public slots: - -private: - QString groupFileName; - QVector groups; - InstanceGroup * implicitGroup; -}; - -#endif // INSTANCELIST_H diff --git a/data/plugin/pluginmanager.cpp b/data/plugin/pluginmanager.cpp new file mode 100644 index 000000000..2f0662936 --- /dev/null +++ b/data/plugin/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 +#include +#include +#include + +#include + +#include + +#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(m_plugins[i]->instance()); + + if (instType) + { + // TODO: Handle errors + InstanceLoader::get().registerInstanceType(instType); + } + } +} diff --git a/data/plugin/pluginmanager.h b/data/plugin/pluginmanager.h new file mode 100644 index 000000000..b93fd6d27 --- /dev/null +++ b/data/plugin/pluginmanager.h @@ -0,0 +1,72 @@ +/* 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. + */ + +#ifndef PLUGINMANAGER_H +#define PLUGINMANAGER_H + +#include +#include +#include + +/*! + * \brief This class is a singleton that manages loading plugins. + */ +class PluginManager : public QObject +{ + Q_OBJECT +public: + /*! + * \brief Gets the plugin manager instance. + */ + static PluginManager &get() { return manager; } + + /*! + * \brief Loads plugins from the given directory. + * This function does \e not initialize the plugins. It simply loads their + * classes. Use the init functions to initialize the various plugin types. + * \param The directory to load plugins from. + * \return True if successful. False on failure. + */ + bool loadPlugins(QString pluginDir); + + /*! + * \brief Checks how many plugins are loaded. + * \return The number of plugins. + */ + int count() { return m_plugins.count(); } + + /*! + * \brief Gets the plugin at the given index. + * \param index The index of the plugin to get. + * \return The plugin at the given index. + */ + QPluginLoader *getPlugin(int index); + + /*! + * \brief Initializes and registers all the instance types. + * This is done by going through the plugin list and registering all of the + * plugins that derive from the InstanceTypeInterface with the InstanceLoader. + */ + void initInstanceTypes(); + +private: + PluginManager(); + + QList m_plugins; + + static PluginManager manager; +}; + +#endif // PLUGINMANAGER_H diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 43c5cd824..e080bbef2 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -27,10 +27,11 @@ #include #include #include +#include -#include "util/osutils.h" -#include "util/userutil.h" -#include "util/pathutils.h" +#include "osutils.h" +#include "userutils.h" +#include "pathutils.h" #include "gui/settingsdialog.h" #include "gui/newinstancedialog.h" @@ -39,14 +40,20 @@ #include "gui/browserdialog.h" #include "gui/aboutdialog.h" -#include "data/appsettings.h" +#include "instancelist.h" +#include "appsettings.h" #include "data/version.h" #include "tasks/logintask.h" +// Opens the given file in the default application. +// TODO: Move this somewhere. +void openInDefaultProgram(QString filename); + MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), - ui(new Ui::MainWindow) + ui(new Ui::MainWindow), + instList(settings->getInstanceDir()) { ui->setupUi(this); @@ -55,8 +62,7 @@ MainWindow::MainWindow(QWidget *parent) : restoreGeometry(settings->getConfig().value("MainWindowGeometry", saveGeometry()).toByteArray()); restoreState(settings->getConfig().value("MainWindowState", saveState()).toByteArray()); - instList.initialLoad("instances"); - ui->instanceView->setModel(&instList); + instList.loadList(); } MainWindow::~MainWindow() @@ -77,7 +83,7 @@ void MainWindow::on_actionViewInstanceFolder_triggered() void MainWindow::on_actionRefresh_triggered() { - instList.initialLoad("instances"); + instList.loadList(); } void MainWindow::on_actionViewCentralModsFolder_triggered() @@ -188,3 +194,8 @@ void MainWindow::openWebPage(QUrl url) browser->load(url); browser->exec(); } + +void openInDefaultProgram(QString filename) +{ + QDesktopServices::openUrl("file:///" + QFileInfo(filename).absolutePath()); +} diff --git a/gui/mainwindow.h b/gui/mainwindow.h index f2dfbc70c..a57b8db46 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -18,7 +18,7 @@ #include -#include "data/instancemodel.h" +#include "instancelist.h" #include "data/loginresponse.h" namespace Ui @@ -75,7 +75,7 @@ private slots: private: Ui::MainWindow *ui; - InstanceModel instList; + InstanceList instList; }; #endif // MAINWINDOW_H diff --git a/gui/mainwindow.ui b/gui/mainwindow.ui index bc58f7f87..137f7e97a 100644 --- a/gui/mainwindow.ui +++ b/gui/mainwindow.ui @@ -35,6 +35,15 @@ + + true + + + true + + + false + Qt::CustomContextMenu diff --git a/gui/settingsdialog.cpp b/gui/settingsdialog.cpp index ab4d18ee9..b3c423803 100644 --- a/gui/settingsdialog.cpp +++ b/gui/settingsdialog.cpp @@ -16,7 +16,7 @@ #include "settingsdialog.h" #include "ui_settingsdialog.h" -#include "data/appsettings.h" +#include "appsettings.h" #include #include diff --git a/java/endian.h b/java/javaendian.h similarity index 100% rename from java/endian.h rename to java/javaendian.h diff --git a/java/membuffer.h b/java/membuffer.h index 48304b9f7..2ea3a69ba 100644 --- a/java/membuffer.h +++ b/java/membuffer.h @@ -3,7 +3,7 @@ #include #include #include -#include "endian.h" +#include "javaendian.h" namespace util { diff --git a/libinstance/CMakeLists.txt b/libinstance/CMakeLists.txt new file mode 100644 index 000000000..d0a9aa085 --- /dev/null +++ b/libinstance/CMakeLists.txt @@ -0,0 +1,47 @@ +project(libmmcinst) + +set(CMAKE_AUTOMOC ON) + +# Find Qt +find_package(Qt5Core REQUIRED) + +# Include Qt headers. +include_directories(${Qt5Base_INCLUDE_DIRS}) +include_directories(${Qt5Network_INCLUDE_DIRS}) + +# Include utility library. +include_directories(${CMAKE_SOURCE_DIR}/libutil/include) + +# Include utility library. +include_directories(${CMAKE_SOURCE_DIR}/libsettings/include) + +SET(LIBINST_HEADERS +include/libinstance_config.h + +include/instancetypeinterface.h + +include/instance.h +include/instancelist.h +include/instanceloader.h + +include/instversion.h +include/instversionlist.h +) + +SET(LIBINST_SOURCES +src/instance.cpp +src/instancelist.cpp +src/instanceloader.cpp + +src/instversion.cpp +src/instversionlist.cpp +) + +# Set the include dir path. +SET(LIBMMCINST_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include" PARENT_SCOPE) + +add_definitions(-DLIBMMCINST_LIBRARY) + +add_library(libmmcinst SHARED ${LIBINST_SOURCES} ${LIBINST_HEADERS}) +qt5_use_modules(libmmcinst Core) +target_link_libraries(libmmcinst libmmcutil libmmcsettings) diff --git a/libinstance/include/instance.h b/libinstance/include/instance.h new file mode 100644 index 000000000..7b3c001db --- /dev/null +++ b/libinstance/include/instance.h @@ -0,0 +1,342 @@ +/* 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. + */ + +#ifndef INSTANCE_H +#define INSTANCE_H + +#include +#include + +#include "appsettings.h" +#include "inifile.h" + +#include "libinstance_config.h" + +#define DEFINE_OVERRIDDEN_SETTING_ADVANCED(funcName, cfgEntryName, typeName) \ + typeName get ## funcName() const { return getField(cfgEntryName, settings->get ## funcName()).value(); } + +#define DEFINE_OVERRIDDEN_SETTING(funcName, typeName) \ + DEFINE_OVERRIDDEN_SETTING_ADVANCED(funcName, STR_VAL(funcName), typeName) + +class InstanceList; + +/*! + * \brief Base class for instances. + * This class implements many functions that are common between instances and + * provides a standard interface for all instances. + * + * To create a new instance type, create a new class inheriting from this class + * and implement the pure virtual functions. + */ +class LIBMMCINST_EXPORT Instance : public SettingsBase +{ + Q_OBJECT +public: + explicit Instance(const QString &rootDir, QObject *parent = 0); + + // Please, for the sake of my (and everyone else's) sanity, at least keep this shit + // *somewhat* organized. Also, documentation is semi-important here. Please don't + // leave undocumented stuff behind. + + + //////// STUFF //////// + + /*! + * \brief Get 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. + * + * \return The instance's ID. + */ + virtual QString id() const; + + /*! + * \brief Gets the path to the instance's root directory. + * \return The path to the instance's root directory. + */ + virtual QString rootDir() const; + + /*! + * \brief Gets the instance list that this instance is a part of. + * Returns NULL if this instance is not in a list + * (the parent is not an InstanceList). + * \return A pointer to the InstanceList containing this instance. + */ + virtual InstanceList *instList() const; + + + //////// FIELDS AND SETTINGS //////// + // Fields are options stored in the instance's config file that are specific + // to instances (not a part of SettingsBase). Settings are things overridden + // from SettingsBase. + + + ////// Fields ////// + + //// General Info //// + + /*! + * \brief Gets this instance's name. + * This is the name that will be displayed to the user. + * \return The instance's name. + * \sa setName + */ + virtual QString name() { return getField("name", "Unnamed Instance").value(); } + + /*! + * \brief Sets the instance's name + * \param val The instance's new name. + */ + virtual void setName(QString val) { setField("name", val); } + + /*! + * \brief Gets the instance's icon key. + * \return The instance's icon key. + * \sa setIconKey() + */ + virtual QString iconKey() const { return getField("iconKey", "default").value(); } + + /*! + * \brief Sets the instance's icon key. + * \param val The new icon key. + */ + virtual void setIconKey(QString val) { setField("iconKey", val); } + + + /*! + * \brief Gets the instance's notes. + * \return The instances notes. + */ + virtual QString notes() const { return getField("notes", "").value(); } + + /*! + * \brief Sets the instance's notes. + * \param val The instance's new notes. + */ + virtual void setNotes(QString val) { setField("notes", val); } + + + /*! + * \brief Checks if the instance's minecraft.jar needs to be rebuilt. + * If this is true, the instance's mods will be reinstalled to its + * minecraft.jar file. This value is automatically set to true when + * the jar mod list changes. + * \return Whether or not the instance's jar file should be rebuilt. + */ + virtual bool shouldRebuild() const { return getField("NeedsRebuild", false).value(); } + + /*! + * \brief Sets whether or not the instance's minecraft.jar needs to be rebuilt. + * \param val Whether the instance's minecraft needs to be rebuilt or not. + */ + virtual void setShouldRebuild(bool val) { setField("NeedsRebuild", val); } + + + //// Version Stuff //// + + /*! + * \brief Sets the instance's current version. + * This value represents the instance's current version. If this value + * is different from intendedVersion(), the instance should be updated. + * This value is updated by the updateCurrentVersion() function. + * \return A string representing the instance's current version. + */ + virtual QString currentVersion() { return getField("JarVersion", "Unknown").value(); } + + /*! + * \brief Sets the instance's current version. + * This is used to keep track of the instance's current version. Don't + * mess with this unless you know what you're doing. + * \param val The new value. + */ + virtual void setCurrentVersion(QString val) { setField("JarVersion", val); } + + + /*! + * \brief Gets the version of LWJGL that this instance should use. + * If no LWJGL version is specified in the instance's config file, + * defaults to "Mojang" + * \return The instance's LWJGL version. + */ + virtual QString lwjglVersion() { return getField("LwjglVersion", "Mojang").value(); } + + /*! + * \brief Sets the version of LWJGL that this instance should use. + * \param val The LWJGL version to use + */ + virtual void setLWJGLVersion(QString val) { setField("LwjglVersion", val); } + + + /*! + * \brief Gets the version that this instance should try to update to. + * If this value differs from currentVersion(), the instance will + * download the intended version when it launches. + * \return The instance's intended version. + */ + virtual QString intendedVersion() { return getField("IntendedJarVersion", currentVersion()).value(); } + + /*! + * \brief Sets the version that this instance should try to update to. + * \param val The instance's new intended version. + */ + virtual void setIntendedVersion(QString val) { setField("IntendedJarVersion", val); } + + + + //// Timestamps //// + + /*! + * \brief Gets the time that the instance was last launched. + * Measured in milliseconds since epoch. QDateTime::currentMSecsSinceEpoch() + * \return The time that the instance was last launched. + */ + virtual qint64 lastLaunch() { return getField("lastLaunchTime", 0).value(); } + + /*! + * \brief Sets the time that the instance was last launched. + * \param val The time to set. Defaults to QDateTime::currentMSecsSinceEpoch() + */ + virtual void setLastLaunch(qint64 val = QDateTime::currentMSecsSinceEpoch()) + { setField("lastLaunchTime", val); } + + + ////// Directories ////// + //! Gets the path to the instance's minecraft folder. + QString minecraftDir() const; + + /*! + * \brief Gets the path to the instance's instance mods folder. + * This is the folder where the jar mods are kept. + */ + QString instModsDir() const; + + //! Gets the path to the instance's bin folder. + QString binDir() const; + + //! Gets the path to the instance's saves folder. + QString savesDir() const; + + //! Gets the path to the instance's mods folder. (.minecraft/mods) + QString mlModsDir() const; + + //! Gets the path to the instance's coremods folder. + QString coreModsDir() const; + + //! Gets the path to the instance's resources folder. + QString resourceDir() const; + + //! Gets the path to the instance's screenshots folder. + QString screenshotsDir() const; + + //! Gets the path to the instance's texture packs folder. + QString texturePacksDir() const; + + + ////// Files ////// + //! Gets the path to the instance's minecraft.jar + QString mcJar() const; + + //! Gets the path to the instance's mcbackup.jar. + QString mcBackup() const; + + //! Gets the path to the instance's config file. + QString configFile() const; + + //! Gets the path to the instance's modlist file. + QString modListFile() const; + + ////// Settings ////// + + //// Java Settings //// + DEFINE_OVERRIDDEN_SETTING_ADVANCED(JavaPath, JPATHKEY, QString) + DEFINE_OVERRIDDEN_SETTING(JvmArgs, QString) + + //// Custom Commands //// + DEFINE_OVERRIDDEN_SETTING(PreLaunchCommand, QString) + DEFINE_OVERRIDDEN_SETTING(PostExitCommand, QString) + + //// Memory //// + DEFINE_OVERRIDDEN_SETTING(MinMemAlloc, int) + DEFINE_OVERRIDDEN_SETTING(MaxMemAlloc, int) + + //// Auto login //// + DEFINE_OVERRIDDEN_SETTING(AutoLogin, bool) + + // This little guy here is to keep Qt Creator from being a dumbass and + // auto-indenting the lines below the macros. Seriously, it's really annoying. + ; + + + //////// 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() = 0; + + /*! + * \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) = 0; + +protected: + /*! + * \brief Gets the value of the given field in the instance's config file. + * If the value isn't in the config file, defVal is returned instead. + * \param name The name of the field in the config file. + * \param defVal The default value. + * \return The value of the given field or defVal if the field doesn't exist. + * \sa setField() + */ + virtual QVariant getField(const QString &name, QVariant defVal = QVariant()) const; + + /*! + * \brief Sets the value of the given field in the config file. + * \param name The name of the field in the config file. + * \param val The value to set the field to. + * \sa getField() + */ + virtual void setField(const QString &name, QVariant val); + + // Overrides for SettingBase stuff. + virtual QVariant getValue(const QString &name, QVariant defVal = QVariant()) const + { return settings->getValue(name, defVal); } + virtual void setValue(const QString &name, QVariant val) + { setField(name, val); } + + INIFile config; + +private: + QString m_rootDir; +}; + +#endif // INSTANCE_H diff --git a/libinstance/include/instancelist.h b/libinstance/include/instancelist.h new file mode 100644 index 000000000..d5b8c196f --- /dev/null +++ b/libinstance/include/instancelist.h @@ -0,0 +1,59 @@ +/* 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. + */ + +#ifndef INSTANCELIST_H +#define INSTANCELIST_H + +#include + +#include + +#include "siglist.h" + +#include "libinstance_config.h" + +class Instance; + +class LIBMMCINST_EXPORT InstanceList : public QObject, public SigList< QSharedPointer > +{ + Q_OBJECT +public: + explicit InstanceList(const QString &instDir, QObject *parent = 0); + + /*! + * \brief Error codes returned by functions in the InstanceList class. + * NoError Indicates that no error occurred. + * UnknownError indicates that an unspecified error occurred. + */ + enum InstListError + { + NoError = 0, + UnknownError + }; + + QString instDir() const { return m_instDir; } + + /*! + * \brief Loads the instance list. + */ + InstListError loadList(); + + DEFINE_SIGLIST_SIGNALS(QSharedPointer); + SETUP_SIGLIST_SIGNALS(QSharedPointer); +protected: + QString m_instDir; +}; + +#endif // INSTANCELIST_H diff --git a/libinstance/include/instanceloader.h b/libinstance/include/instanceloader.h new file mode 100644 index 000000000..96be36fb3 --- /dev/null +++ b/libinstance/include/instanceloader.h @@ -0,0 +1,140 @@ +/* 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. + */ + +#ifndef INSTANCELOADER_H +#define INSTANCELOADER_H + +#include +#include +#include + +#include "libinstance_config.h" + +class InstanceTypeInterface; +class Instance; + +typedef QList InstTypeList; + +/*! + * \brief The InstanceLoader is a singleton that manages all of the instance types and handles loading and creating instances. + * Instance types are registered with the instance loader through its registerInstType() function. + * Creating instances is done through the InstanceLoader's createInstance() function. This function takes + */ +class LIBMMCINST_EXPORT InstanceLoader : public QObject +{ + Q_OBJECT +public: + /*! + * \brief Gets a reference to the instance loader. + */ + static InstanceLoader &get() { return loader; } + + /*! + * \brief Error codes returned by functions in the InstanceLoader and InstanceType classes. + * + * - NoError indicates that no error occurred. + * - OtherError indicates that an unspecified error occurred. + * - TypeIDExists is returned by registerInstanceType() if the ID of the type being registered already exists. + * - TypeNotRegistered is returned by createInstance() and loadInstance() when the given type is not registered. + * - InstExists is returned by createInstance() if the given instance directory is already an instance. + * - NotAnInstance is returned by loadInstance() if the given instance directory is not a valid instance. + * - WrongInstType is returned by loadInstance() if the given instance directory's type doesn't match the given type. + * - CantCreateDir is returned by createInstance( if the given instance directory can't be created.) + */ + enum InstTypeError + { + NoError = 0, + OtherError, + + TypeIDExists, + + TypeNotRegistered, + InstExists, + NotAnInstance, + WrongInstType, + CantCreateDir + }; + + /*! + * \brief Registers the given InstanceType with the instance loader. + * + * \param type The InstanceType to register. + * \return An InstTypeError error code. + * - TypeIDExists if the given type's is already registered to another instance type. + */ + InstTypeError registerInstanceType(InstanceTypeInterface *type); + + /*! + * \brief Creates an instance with the given type and stores it in inst. + * + * \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 InstTypeError error code. + * - TypeNotRegistered if the given type is not registered with the InstanceLoader. + * - InstExists if the given instance directory is already an instance. + * - CantCreateDir if the given instance directory cannot be created. + */ + InstTypeError createInstance(Instance *&inst, const InstanceTypeInterface *type, const QString &instDir); + + /*! + * \brief Loads an instance from the given directory. + * + * \param inst Pointer to store the loaded instance in. + * \param type The type of instance to load. + * \param instDir The instance's directory. + * \return An InstTypeError error code. + * - TypeNotRegistered if the given type is not registered with the InstanceLoader. + * - NotAnInstance if the given instance directory isn't a valid instance. + * - WrongInstType if the given instance directory's type isn't the same as the given type. + */ + InstTypeError loadInstance(Instance *&inst, const InstanceTypeInterface *type, const QString &instDir); + + /*! + * \brief Loads an instance from the given directory. + * Checks the instance's INI file to figure out what the instance's type is first. + * \param inst Pointer to store the loaded instance in. + * \param instDir The instance's directory. + * \return An InstTypeError error code. + * - TypeNotRegistered if the instance's type is not registered with the InstanceLoader. + * - NotAnInstance if the given instance directory isn't a valid instance. + */ + InstTypeError loadInstance(Instance *&inst, const QString &instDir); + + /*! + * \brief Finds an instance type with the given ID. + * If one cannot be found, returns NULL. + * + * \param id The ID of the type to find. + * \return The type with the given ID. NULL if none were found. + */ + const InstanceTypeInterface *findType(const QString &id); + + /*! + * \brief Gets a list of the registered instance types. + * + * \return A list of instance types. + */ + InstTypeList typeList(); + +private: + InstanceLoader(); + + QMap m_typeMap; + + static InstanceLoader loader; +}; + +#endif // INSTANCELOADER_H diff --git a/libinstance/include/instancetypeinterface.h b/libinstance/include/instancetypeinterface.h new file mode 100644 index 000000000..30a12d99d --- /dev/null +++ b/libinstance/include/instancetypeinterface.h @@ -0,0 +1,86 @@ +/* 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. + */ + +#ifndef INSTANCETYPE_H +#define INSTANCETYPE_H + +#include + +#include "instanceloader.h" + +//! The InstanceTypeInterface's interface ID. +#define InstanceTypeInterface_IID "net.forkk.MultiMC.InstanceTypeInterface/0.1" + +/*! + * \brief The InstanceType class is an interface for all instance types. + * InstanceTypes are usually provided by plugins. + * It handles loading and creating instances of a certain type. There should be + * one of these for each type of instance and they should be registered with the + * InstanceLoader. + * To create an instance, the InstanceLoader calls the type's createInstance() + * function. Loading is done through the loadInstance() function. + */ +class InstanceTypeInterface +{ +public: + friend class InstanceLoader; + + /*! + * \brief Gets the ID for this instance type. + * The type ID should be unique as it is used to identify the type + * of instances when they are loaded. + * Changing this value at runtime results in undefined behavior. + * \return This instance type's ID string. + */ + virtual QString typeID() const = 0; + + /*! + * \brief Gets the name of this instance type as it is displayed to the user. + * \return The instance type's display name. + */ + virtual QString displayName() const = 0; + + /*! + * \brief Gets a longer, more detailed description of this instance type. + * \return The instance type's description. + */ + virtual QString description() const = 0; + +protected: + /*! + * \brief Creates an instance and stores it in inst. + * \param inst Pointer to store the created instance in. + * \param instDir The instance's directory. + * \return An InstTypeError error code. + * TypeNotRegistered if the given type is not registered with the InstanceLoader. + * InstExists if the given instance directory is already an instance. + */ + virtual InstanceLoader::InstTypeError createInstance(Instance *&inst, const QString &instDir) const = 0; + + /*! + * \brief Loads an instance from the given directory. + * \param inst Pointer to store the loaded instance in. + * \param instDir The instance's directory. + * \return An InstTypeError error code. + * TypeNotRegistered if the given type is not registered with the InstanceLoader. + * NotAnInstance if the given instance directory isn't a valid instance. + * WrongInstType if the given instance directory's type isn't an instance of this type. + */ + virtual InstanceLoader::InstTypeError loadInstance(Instance *&inst, const QString &instDir) const = 0; +}; + +Q_DECLARE_INTERFACE(InstanceTypeInterface, InstanceTypeInterface_IID) + +#endif // INSTANCETYPE_H diff --git a/libinstance/include/instversion.h b/libinstance/include/instversion.h new file mode 100644 index 000000000..c505c5a3d --- /dev/null +++ b/libinstance/include/instversion.h @@ -0,0 +1,53 @@ +/* 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. + */ + +#ifndef INSTVERSION_H +#define INSTVERSION_H + +#include + +#include "libinstance_config.h" + +class InstVersionList; + +class LIBMMCINST_EXPORT InstVersion : public QObject +{ + Q_OBJECT +public: + // Constructs a new InstVersion with the given parent. The parent *must* + // be the InstVersionList that contains this InstVersion. The InstVersion + // should be added to the list immediately after being created as any calls + // to id() will likely fail unless the InstVersion is in a list. + explicit InstVersion(InstVersionList *parent = 0); + + // Returns this InstVersion's ID. This is usually just the InstVersion's index + // within its InstVersionList, but not always. + // If this InstVersion is not in an InstVersionList, returns -1. + virtual int id() const = 0; + + // Returns this InstVersion's name. This is displayed to the user in the GUI + // and is usually just the version number ("1.4.7"), for example. + virtual QString name() const = 0; + + // Returns this InstVersion's name. This is usually displayed to the user + // in the GUI and specifies what kind of version this is. For example: it + // could be "Snapshot", "Latest Version", "MCNostalgia", etc. + virtual QString type() const = 0; + + // Returns the version list that this InstVersion is a part of. + virtual InstVersionList *versionList() const; +}; + +#endif // INSTVERSION_H diff --git a/libinstance/include/instversionlist.h b/libinstance/include/instversionlist.h new file mode 100644 index 000000000..2cd9ed1e4 --- /dev/null +++ b/libinstance/include/instversionlist.h @@ -0,0 +1,45 @@ +/* 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. + */ + +#ifndef INSTVERSIONLIST_H +#define INSTVERSIONLIST_H + +#include + +#include "libinstance_config.h" + +class InstVersion; + +// Class that each instance type's version list derives from. Version lists are +// the lists that keep track of the available game versions for that instance. +// This list will not be loaded on startup. It will be loaded when the list's +// load function is called. +class LIBMMCINST_EXPORT InstVersionList : public QObject +{ + Q_OBJECT +public: + explicit InstVersionList(); + + // Reloads the version list. + virtual void loadVersionList() = 0; + + // Gets the version at the given index. + virtual const InstVersion *at(int i) const = 0; + + // Returns the number of versions in the list. + virtual int count() const = 0; +}; + +#endif // INSTVERSIONLIST_H diff --git a/libinstance/include/libinstance_config.h b/libinstance/include/libinstance_config.h new file mode 100644 index 000000000..2e6dc8847 --- /dev/null +++ b/libinstance/include/libinstance_config.h @@ -0,0 +1,27 @@ +/* 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. + */ + +//#ifndef LIBINSTANCE_CONFIG_H +//#define LIBINSTANCE_CONFIG_H + +#include + +#ifdef LIBMMCINST_LIBRARY +# define LIBMMCINST_EXPORT Q_DECL_EXPORT +#else +# define LIBMMCINST_EXPORT Q_DECL_IMPORT +#endif + +//#endif // LIBINSTANCE_CONFIG_H diff --git a/libinstance/src/instance.cpp b/libinstance/src/instance.cpp new file mode 100644 index 000000000..c79c02138 --- /dev/null +++ b/libinstance/src/instance.cpp @@ -0,0 +1,110 @@ +/* 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 + +#include "pathutils.h" + +Instance::Instance(const QString &rootDir, QObject *parent) : + SettingsBase(parent) +{ + m_rootDir = rootDir; + config.loadFile(PathCombine(rootDir, "instance.cfg")); +} + +QString Instance::id() const +{ + return QFileInfo(rootDir()).baseName(); +} + +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.path(); + } + else + { + return mcDir.path(); + } +} + +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"); +} + +QVariant Instance::getField(const QString &name, QVariant defVal) const +{ + return config.get(name, defVal); +} + +void Instance::setField(const QString &name, QVariant val) +{ + config.set(name, val); +} diff --git a/libinstance/src/instancelist.cpp b/libinstance/src/instancelist.cpp new file mode 100644 index 000000000..3b0b668f3 --- /dev/null +++ b/libinstance/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 +#include +#include + +#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 inst(instPtr); + + qDebug(QString("Loaded instance %1").arg(inst->name()).toUtf8()); + inst->setParent(this); + append(QSharedPointer(inst)); + } + } + } + + return NoError; +} diff --git a/libinstance/src/instanceloader.cpp b/libinstance/src/instanceloader.cpp new file mode 100644 index 000000000..9d98230f9 --- /dev/null +++ b/libinstance/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 + +#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::iterator iter = m_typeMap.begin(); iter != m_typeMap.end(); iter++) + { + typeList.append(*iter); + } + + return typeList; +} diff --git a/libinstance/src/instversion.cpp b/libinstance/src/instversion.cpp new file mode 100644 index 000000000..cedb61df3 --- /dev/null +++ b/libinstance/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/data/stdinstance.cpp b/libinstance/src/instversionlist.cpp similarity index 83% rename from data/stdinstance.cpp rename to libinstance/src/instversionlist.cpp index 4618f5ca8..e171cfa5a 100644 --- a/data/stdinstance.cpp +++ b/libinstance/src/instversionlist.cpp @@ -13,10 +13,9 @@ * limitations under the License. */ -#include "stdinstance.h" +#include "include/instversionlist.h" -StdInstance::StdInstance(QString rootDir, QObject* parent) : - InstanceBase(rootDir, parent) +InstVersionList::InstVersionList() : + QObject(NULL) { - } diff --git a/libsettings/CMakeLists.txt b/libsettings/CMakeLists.txt new file mode 100644 index 000000000..2cf723653 --- /dev/null +++ b/libsettings/CMakeLists.txt @@ -0,0 +1,30 @@ +project(libmmcsettings) + +# Find Qt +find_package(Qt5Core REQUIRED) + +# Include Qt headers. +include_directories(${Qt5Base_INCLUDE_DIRS}) +include_directories(${Qt5Network_INCLUDE_DIRS}) + +# Include utils library headers. +include_directories(${CMAKE_SOURCE_DIR}/libutil/include) + +SET(LIBSETTINGS_HEADERS +include/libsettings_config.h + +include/appsettings.h +) + +SET(LIBSETTINGS_SOURCES +src/appsettings.cpp +) + +# Set the include dir path. +SET(LIBMMCSETTINGS_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include" PARENT_SCOPE) + +add_definitions(-DLIBMMCSETTINGS_LIBRARY) + +add_library(libmmcsettings SHARED ${LIBSETTINGS_SOURCES} ${LIBSETTINGS_HEADERS}) +qt5_use_modules(libmmcsettings Core) +target_link_libraries(libmmcsettings libmmcutil) diff --git a/data/appsettings.h b/libsettings/include/appsettings.h similarity index 85% rename from data/appsettings.h rename to libsettings/include/appsettings.h index a9068bfdf..795156185 100644 --- a/data/appsettings.h +++ b/libsettings/include/appsettings.h @@ -18,11 +18,13 @@ #include #include -#include +//#include #include -#include "util/apputils.h" -#include "util/osutils.h" +#include +#include + +#include "libsettings_config.h" #if WINDOWS #define JPATHKEY "JavaPathWindows" @@ -39,10 +41,8 @@ #define DEFINE_SETTING(name, valType, defVal) \ DEFINE_SETTING_ADVANCED(name, STR_VAL(name), valType, defVal) -#define DEFINE_OVERRIDE_SETTING(overrideName) \ - -class SettingsBase : public QObject +class LIBMMCSETTINGS_EXPORT SettingsBase : public QObject { Q_OBJECT public: @@ -66,9 +66,10 @@ public: DEFINE_SETTING(InstanceToolbarPosition, QPoint, QPoint()) // Console Colors - DEFINE_SETTING(SysMessageColor, QColor, QColor(Qt::blue)) - DEFINE_SETTING(StdOutColor, QColor, QColor(Qt::black)) - DEFINE_SETTING(StdErrColor, QColor, QColor(Qt::red)) + // Currently commented out because QColor is a part of QtGUI +// DEFINE_SETTING(SysMessageColor, QColor, QColor(Qt::blue)) +// DEFINE_SETTING(StdOutColor, QColor, QColor(Qt::black)) +// DEFINE_SETTING(StdErrColor, QColor, QColor(Qt::red)) // Window Size DEFINE_SETTING(LaunchCompatMode, bool, false) @@ -91,12 +92,11 @@ public: DEFINE_SETTING(PreLaunchCommand, QString, "") DEFINE_SETTING(PostExitCommand, QString, "") -protected: virtual QVariant getValue(const QString& name, QVariant defVal = QVariant()) const = 0; virtual void setValue(const QString& name, QVariant val) = 0; }; -class AppSettings : public SettingsBase +class LIBMMCSETTINGS_EXPORT AppSettings : public SettingsBase { Q_OBJECT public: @@ -104,16 +104,16 @@ public: QSettings& getConfig() { return config; } -protected: virtual QVariant getValue(const QString &name, QVariant defVal = QVariant()) const; virtual void setValue(const QString& name, QVariant val); - + +protected: QSettings config; }; #undef DEFINE_SETTING_ADVANCED #undef DEFINE_SETTING -extern AppSettings* settings; +LIBMMCSETTINGS_EXPORT extern AppSettings* settings; #endif // APPSETTINGS_H diff --git a/libsettings/include/libsettings_config.h b/libsettings/include/libsettings_config.h new file mode 100644 index 000000000..05df5bfae --- /dev/null +++ b/libsettings/include/libsettings_config.h @@ -0,0 +1,27 @@ +/* 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. + */ + +#ifndef LIBINSTANCE_CONFIG_H +#define LIBINSTANCE_CONFIG_H + +#include + +#ifdef LIBMMCSETTINGS_LIBRARY +# define LIBMMCSETTINGS_EXPORT Q_DECL_EXPORT +#else +# define LIBMMCSETTINGS_EXPORT Q_DECL_IMPORT +#endif + +#endif // LIBINSTANCE_CONFIG_H diff --git a/data/appsettings.cpp b/libsettings/src/appsettings.cpp similarity index 96% rename from data/appsettings.cpp rename to libsettings/src/appsettings.cpp index 1d9c4312a..8fe9b8ad9 100644 --- a/data/appsettings.cpp +++ b/libsettings/src/appsettings.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "appsettings.h" +#include "include/appsettings.h" AppSettings* settings; diff --git a/libutil/CMakeLists.txt b/libutil/CMakeLists.txt new file mode 100644 index 000000000..b934d4c06 --- /dev/null +++ b/libutil/CMakeLists.txt @@ -0,0 +1,57 @@ +project(libmmcutil) + +######## Set compiler flags ######## +IF(APPLE) + # assume clang 4.1.0+, add C++0x/C++11 stuff + message(STATUS "Using APPLE CMAKE_CXX_FLAGS") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -stdlib=libc++") +ELSEIF(UNIX) + # assume GCC, add C++0x/C++11 stuff + MESSAGE(STATUS "Using UNIX CMAKE_CXX_FLAGS") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") +ELSEIF(MINGW) + MESSAGE(STATUS "Using MINGW CMAKE_CXX_FLAGS") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x") +ENDIF() + + +# Find Qt +find_package(Qt5Core REQUIRED) + +# Include Qt headers. +include_directories(${Qt5Base_INCLUDE_DIRS}) +include_directories(${Qt5Network_INCLUDE_DIRS}) + +SET(LIBUTIL_HEADERS +include/libutil_config.h + +include/apputils.h + +include/pathutils.h +include/osutils.h +include/userutils.h +include/cmdutils.h + +include/inifile.h + +include/siglist.h +include/siglist_impl.h +) + +SET(LIBUTIL_SOURCES +src/pathutils.cpp +src/osutils.cpp +src/userutils.cpp +src/cmdutils.cpp + +src/inifile.cpp +) + +# Set the include dir path. +SET(LIBMMCUTIL_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include" PARENT_SCOPE) + +add_definitions(-DLIBMMCUTIL_LIBRARY) + +add_library(libmmcutil SHARED ${LIBUTIL_SOURCES} ${LIBUTIL_HEADERS}) +qt5_use_modules(libmmcutil Core) +target_link_libraries(libmmcutil) diff --git a/util/apputils.h b/libutil/include/apputils.h similarity index 100% rename from util/apputils.h rename to libutil/include/apputils.h diff --git a/util/cmdutils.h b/libutil/include/cmdutils.h similarity index 99% rename from util/cmdutils.h rename to libutil/include/cmdutils.h index 690c96fd5..fc1162d9c 100644 --- a/util/cmdutils.h +++ b/libutil/include/cmdutils.h @@ -26,7 +26,7 @@ #include /** - * @file utils/cmdutils.h + * @file libutil/include/cmdutils.h * @brief commandline parsing utilities */ diff --git a/data/inifile.h b/libutil/include/inifile.h similarity index 91% rename from data/inifile.h rename to libutil/include/inifile.h index 757838598..1280c7e3d 100644 --- a/data/inifile.h +++ b/libutil/include/inifile.h @@ -20,8 +20,10 @@ #include #include +#include "libutil_config.h" + // Sectionless INI parser (for instance config files) -class INIFile : public QMap +class LIBMMCUTIL_EXPORT INIFile : public QMap { public: explicit INIFile(); diff --git a/data/stdinstance.h b/libutil/include/libutil_config.h similarity index 71% rename from data/stdinstance.h rename to libutil/include/libutil_config.h index 79b87601f..41766184b 100644 --- a/data/stdinstance.h +++ b/libutil/include/libutil_config.h @@ -13,16 +13,15 @@ * limitations under the License. */ -#ifndef STDINSTANCE_H -#define STDINSTANCE_H +#ifndef LIBUTIL_CONFIG_H +#define LIBUTIL_CONFIG_H -#include "instancebase.h" +#include -// Standard client instance. -class StdInstance : public InstanceBase -{ -public: - explicit StdInstance(QString rootDir, QObject *parent = 0); -}; +#ifdef LIBMMCUTIL_LIBRARY +# define LIBMMCUTIL_EXPORT Q_DECL_EXPORT +#else +# define LIBMMCUTIL_EXPORT Q_DECL_IMPORT +#endif -#endif // STDINSTANCE_H +#endif // LIBUTIL_CONFIG_H diff --git a/util/osutils.h b/libutil/include/osutils.h similarity index 89% rename from util/osutils.h rename to libutil/include/osutils.h index f779ea2df..c5d4bb613 100644 --- a/util/osutils.h +++ b/libutil/include/osutils.h @@ -26,7 +26,4 @@ #define LINUX 1 #endif -// Opens the given file in the default application. -void openInDefaultProgram(QString filename); - #endif // OSUTILS_H diff --git a/util/pathutils.h b/libutil/include/pathutils.h similarity index 74% rename from util/pathutils.h rename to libutil/include/pathutils.h index 1922e3a08..d5f106efb 100644 --- a/util/pathutils.h +++ b/libutil/include/pathutils.h @@ -18,9 +18,11 @@ #include -QString PathCombine(QString path1, QString path2); -QString PathCombine(QString path1, QString path2, QString path3); +#include "libutil_config.h" -QString AbsolutePath(QString path); +LIBMMCUTIL_EXPORT QString PathCombine(QString path1, QString path2); +LIBMMCUTIL_EXPORT QString PathCombine(QString path1, QString path2, QString path3); + +LIBMMCUTIL_EXPORT QString AbsolutePath(QString path); #endif // PATHUTILS_H diff --git a/data/siglist.h b/libutil/include/siglist.h similarity index 95% rename from data/siglist.h rename to libutil/include/siglist.h index b6432b6e2..dcae7c041 100644 --- a/data/siglist.h +++ b/libutil/include/siglist.h @@ -26,7 +26,6 @@ template class SigList : public QList { - public: explicit SigList() : QList() {} @@ -35,11 +34,11 @@ public: virtual void clear(); - virtual void erase(iterator pos); - virtual void erase(iterator first, iterator last); + virtual void erase(typename QList::iterator pos); + virtual void erase(typename QList::iterator first, typename QList::iterator last); virtual void insert(int i, const T &t); - virtual void insert(iterator before, const T &t); + virtual void insert(typename QList::iterator before, const T &t); virtual void move(int from, int to); diff --git a/data/siglist_imp.h b/libutil/include/siglist_impl.h similarity index 79% rename from data/siglist_imp.h rename to libutil/include/siglist_impl.h index 16ddd9b03..5cdc632a0 100644 --- a/data/siglist_imp.h +++ b/libutil/include/siglist_impl.h @@ -19,7 +19,7 @@ template void SigList::append(const T &value) { QList::append(value); - onItemAdded(value, length() - 1); + onItemAdded(value, QList::length() - 1); } template @@ -32,7 +32,7 @@ void SigList::prepend(const T &value) template void SigList::append(const QList &other) { - int index = length(); + int index = QList::length(); QList::append(other); onItemsAdded(other, index); } @@ -45,21 +45,21 @@ void SigList::clear() } template -void SigList::erase(QList::iterator pos) +void SigList::erase(typename QList::iterator pos) { T value = *pos; - int index = indexOf(*pos); + int index = QList::indexOf(*pos); QList::erase(pos); onItemRemoved(value, index); } template -void SigList::erase(QList::iterator first, QList::iterator last) +void SigList::erase(typename QList::iterator first, typename QList::iterator last) { QList removedValues; - int firstIndex = indexOf(*first); + int firstIndex = QList::indexOf(*first); - for (QList::iterator iter = first; iter < last; iter++) + for (auto iter = first; iter < last; iter++) { removedValues << *iter; QList::erase(iter); @@ -76,16 +76,16 @@ void SigList::insert(int i, const T &t) } template -void SigList::insert(QList::iterator before, const T &t) +void SigList::insert(typename QList::iterator before, const T &t) { QList::insert(before, t); - onItemAdded(t, indexOf(t)); + onItemAdded(t, QList::indexOf(t)); } template void SigList::move(int from, int to) { - const T &item = at(from); + const T &item = QList::at(from); QList::move(from, to); onItemMoved(item, from, to); } @@ -101,7 +101,7 @@ int SigList::removeAll(const T &t) template bool SigList::removeOne(const T &t) { - int index = indexOf(t); + int index = QList::indexOf(t); if (QList::removeOne(t)) { onItemRemoved(t, index); @@ -120,8 +120,8 @@ void SigList::swap(QList &other) template void SigList::swap(int i, int j) { - const T &item1 = at(i); - const T &item2 = at(j); + const T &item1 = QList::at(i); + const T &item2 = QList::at(j); QList::swap(i, j); onItemMoved(item1, i, j); onItemMoved(item2, j, i); @@ -144,7 +144,7 @@ T SigList::takeFirst() template T SigList::takeLast() { - return takeAt(length() - 1); + return takeAt(QList::length() - 1); } template diff --git a/util/userutil.h b/libutil/include/userutils.h similarity index 87% rename from util/userutil.h rename to libutil/include/userutils.h index 11c13ed08..c99e758ea 100644 --- a/util/userutil.h +++ b/libutil/include/userutils.h @@ -1,5 +1,5 @@ -#ifndef USERUTIL_H -#define USERUTIL_H +#ifndef USERUTILS_H +#define USERUTILS_H #include @@ -14,4 +14,4 @@ namespace Util bool createShortCut(QString location, QString dest, QStringList args, QString name, QString iconLocation); } -#endif // USERUTIL_H +#endif // USERUTILS_H diff --git a/util/cmdutils.cpp b/libutil/src/cmdutils.cpp similarity index 99% rename from util/cmdutils.cpp rename to libutil/src/cmdutils.cpp index bd52cf8f2..cff7acb91 100644 --- a/util/cmdutils.cpp +++ b/libutil/src/cmdutils.cpp @@ -15,10 +15,10 @@ * limitations under the License. */ -#include "cmdutils.h" +#include "include/cmdutils.h" /** - * @file utils/cmdutils.cpp + * @file libutil/src/cmdutils.cpp */ namespace Util { diff --git a/data/inifile.cpp b/libutil/src/inifile.cpp similarity index 98% rename from data/inifile.cpp rename to libutil/src/inifile.cpp index 2d68caf6f..43545a4a8 100644 --- a/data/inifile.cpp +++ b/libutil/src/inifile.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "inifile.h" +#include "include/inifile.h" #include #include diff --git a/util/osutils.cpp b/libutil/src/osutils.cpp similarity index 78% rename from util/osutils.cpp rename to libutil/src/osutils.cpp index 6b0955185..9a85d1e54 100644 --- a/util/osutils.cpp +++ b/libutil/src/osutils.cpp @@ -13,13 +13,7 @@ * limitations under the License. */ -#include "osutils.h" +#include "include/osutils.h" -#include #include #include - -void openInDefaultProgram(QString filename) -{ - QDesktopServices::openUrl("file:///" + QFileInfo(filename).absolutePath()); -} diff --git a/util/pathutils.cpp b/libutil/src/pathutils.cpp similarity index 97% rename from util/pathutils.cpp rename to libutil/src/pathutils.cpp index 8610b80d9..8e91bf316 100644 --- a/util/pathutils.cpp +++ b/libutil/src/pathutils.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "pathutils.h" +#include "include/pathutils.h" #include #include diff --git a/util/userutil.cpp b/libutil/src/userutils.cpp similarity index 96% rename from util/userutil.cpp rename to libutil/src/userutils.cpp index 9a7b2e12a..f3778d083 100644 --- a/util/userutil.cpp +++ b/libutil/src/userutils.cpp @@ -1,11 +1,11 @@ -#include "userutil.h" +#include "include/userutils.h" #include #include #include -#include "osutils.h" -#include "pathutils.h" +#include "include/osutils.h" +#include "include/pathutils.h" // Win32 crap #if WINDOWS diff --git a/main.cpp b/main.cpp index fb7a50614..4a4d8e7e0 100644 --- a/main.cpp +++ b/main.cpp @@ -1,6 +1,7 @@ /* Copyright 2013 MultiMC Contributors * - * Authors: Orochimarufan + * Authors: Andrew Okin + * Orochimarufan * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,10 +23,13 @@ #include "gui/mainwindow.h" -#include "data/appsettings.h" +#include "appsettings.h" #include "data/loginresponse.h" -#include "util/cmdutils.h" +#include "data/plugin/pluginmanager.h" + +#include "pathutils.h" +#include "cmdutils.h" #include "config.h" @@ -121,11 +125,15 @@ int main(int argc, char *argv[]) // load settings settings = new AppSettings(&app); - + // Register meta types. qRegisterMetaType("LoginResponse"); - - // show window + + // Initialize plugins. + PluginManager::get().loadPlugins(PathCombine(qApp->applicationDirPath(), "plugins")); + PluginManager::get().initInstanceTypes(); + + // show main window MainWindow mainWin; mainWin.show(); diff --git a/multimc.rc b/multimc.rc new file mode 100644 index 000000000..decf7d3ab --- /dev/null +++ b/multimc.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "resources/icons/MultiMC.ico" diff --git a/plugins/stdinstance/CMakeLists.txt b/plugins/stdinstance/CMakeLists.txt new file mode 100644 index 000000000..0bb466ec5 --- /dev/null +++ b/plugins/stdinstance/CMakeLists.txt @@ -0,0 +1,49 @@ +project(stdinstance) + +ADD_DEFINITIONS(-DQT_PLUGIN) + +# Find Qt +find_package(Qt5Core REQUIRED) +find_package(Qt5Network REQUIRED) + +# Include Qt headers. +include_directories(${Qt5Base_INCLUDE_DIRS}) +include_directories(${Qt5Network_INCLUDE_DIRS}) + +# Include the Java library. +include_directories(${CMAKE_SOURCE_DIR}/java) + +# Include utils library headers. +include_directories(${CMAKE_SOURCE_DIR}/libutil/include) + +# Include settings library headers. +include_directories(${CMAKE_SOURCE_DIR}/libsettings/include) + +# Include instance library headers. +include_directories(${CMAKE_SOURCE_DIR}libinstance/include) + +SET(STDINST_HEADERS +stdinstancetype.h +stdinstance.h +) + +SET(STDINST_SOURCES +stdinstancetype.cpp +stdinstance.cpp +) + +add_library(stdinstance SHARED ${STDINST_SOURCES} ${STDINST_HEADERS}) + +set_target_properties(stdinstance PROPERTIES PREFIX "") +set_target_properties(stdinstance PROPERTIES RUNTIME_OUTPUT_DIRECTORY "..") + +qt5_use_modules(stdinstance Core Network) +target_link_libraries(stdinstance +quazip +patchlib + +# Link the util, settings, and instance libraries. +libmmcutil +libmmcsettings +libmmcinst +) diff --git a/plugins/stdinstance/stdinstance.cpp b/plugins/stdinstance/stdinstance.cpp new file mode 100644 index 000000000..12d86bbcc --- /dev/null +++ b/plugins/stdinstance/stdinstance.cpp @@ -0,0 +1,54 @@ +/* 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 "stdinstance.h" + +#include + +#include + +StdInstance::StdInstance(const QString &rootDir, QObject *parent) : + Instance(rootDir, parent) +{ + +} + +bool StdInstance::shouldUpdateCurrentVersion() +{ + QFileInfo jar(mcJar()); + return jar.lastModified().toUTC().toMSecsSinceEpoch() != lastVersionUpdate(); +} + +void StdInstance::updateCurrentVersion(bool keepCurrent) +{ + QFileInfo jar(mcJar()); + + if(!jar.exists()) + { + setLastVersionUpdate(0); + setCurrentVersion("Unknown"); + return; + } + + qint64 time = jar.lastModified().toUTC().toMSecsSinceEpoch(); + + setLastVersionUpdate(time); + if (!keepCurrent) + { + // TODO: Implement GetMinecraftJarVersion function. + QString newVersion = "Unknown";//javautils::GetMinecraftJarVersion(jar.absoluteFilePath()); + setCurrentVersion(newVersion); + } +} diff --git a/plugins/stdinstance/stdinstance.h b/plugins/stdinstance/stdinstance.h new file mode 100644 index 000000000..d812a9b07 --- /dev/null +++ b/plugins/stdinstance/stdinstance.h @@ -0,0 +1,36 @@ +/* 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. + */ + +#ifndef STDINSTANCE_H +#define STDINSTANCE_H + +#include + +class StdInstance : public Instance +{ + Q_OBJECT +public: + explicit StdInstance(const QString &rootDir, QObject *parent = 0); + + virtual bool shouldUpdateCurrentVersion(); + + virtual void updateCurrentVersion(bool keepCurrent); + + ////// TIMESTAMPS ////// + virtual qint64 lastVersionUpdate() { return getField("lastVersionUpdate", 0).value(); } + virtual void setLastVersionUpdate(qint64 val) { setField("lastVersionUpdate", val); } +}; + +#endif // STDINSTANCE_H diff --git a/plugins/stdinstance/stdinstance.json b/plugins/stdinstance/stdinstance.json new file mode 100644 index 000000000..704f0b733 --- /dev/null +++ b/plugins/stdinstance/stdinstance.json @@ -0,0 +1,8 @@ +{ + "api": "MultiMC5-API-1", + + "name": "Standard Instance Plugin", + "summary": "A plugin that provides standard Minecraft instances.", + "description": "This is a built-in plugin that provides the standard Minecraft instance.", + "version": "0.1" +} diff --git a/plugins/stdinstance/stdinstancetype.cpp b/plugins/stdinstance/stdinstancetype.cpp new file mode 100644 index 000000000..5a3a6649b --- /dev/null +++ b/plugins/stdinstance/stdinstancetype.cpp @@ -0,0 +1,58 @@ +/* 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 "stdinstancetype.h" + +#include +#include + +#include "stdinstance.h" + +StdInstanceType::StdInstanceType(QObject *parent) : + QObject(parent) +{ + +} + +InstanceLoader::InstTypeError StdInstanceType::createInstance(Instance *&inst, + const QString &instDir) const +{ + QFileInfo rootDir(instDir); + + if (!rootDir.exists() && !QDir().mkdir(rootDir.path())) + { + return InstanceLoader::CantCreateDir; + } + + StdInstance *stdInst = new StdInstance(instDir); + + // TODO: Verify that the instance is valid. + + inst = stdInst; + + return InstanceLoader::NoError; +} + +InstanceLoader::InstTypeError StdInstanceType::loadInstance(Instance *&inst, + const QString &instDir) const +{ + StdInstance *stdInst = new StdInstance(instDir); + + // TODO: Verify that the instance is valid. + + inst = stdInst; + + return InstanceLoader::NoError; +} diff --git a/plugins/stdinstance/stdinstancetype.h b/plugins/stdinstance/stdinstancetype.h new file mode 100644 index 000000000..b8382a971 --- /dev/null +++ b/plugins/stdinstance/stdinstancetype.h @@ -0,0 +1,42 @@ +/* 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. + */ + +#ifndef STDINSTANCETYPE_H +#define STDINSTANCETYPE_H + +#include + +#define StdInstanceType_IID "net.forkk.MultiMC.StdInstanceType/0.1" + +class StdInstanceType : public QObject, InstanceTypeInterface +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID StdInstanceType_IID FILE "stdinstance.json") + Q_INTERFACES(InstanceTypeInterface) +public: + explicit StdInstanceType(QObject *parent = 0); + + virtual QString typeID() const { return "net.forkk.MultiMC.StdInstance"; } + + virtual QString displayName() const { return "Standard Instance"; } + + virtual QString description() const { return "A standard Minecraft instance."; } + + virtual InstanceLoader::InstTypeError createInstance(Instance *&inst, const QString &instDir) const; + + virtual InstanceLoader::InstTypeError loadInstance(Instance *&inst, const QString &instDir) const; +}; + +#endif // STDINSTANCETYPE_H diff --git a/resources/icons/MultiMC.ico b/resources/icons/MultiMC.ico new file mode 100644 index 000000000..734af0fb1 Binary files /dev/null and b/resources/icons/MultiMC.ico differ