diff options
64 files changed, 1001 insertions, 467 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 343f6ac8..1bb3126b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,11 @@ SET(CMAKE_AUTOMOC ON) SET(CMAKE_INCLUDE_CURRENT_DIR ON) SET(FILES_TO_TRANSLATE ) +######## Set module path ######## +SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/") +SET(MMC_SRC "${PROJECT_SOURCE_DIR}") +SET(MMC_BIN "${PROJECT_BINARY_DIR}") + # Output all executables and shared libs in the main build folder, not in subfolders. SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) @@ -49,8 +54,9 @@ include_directories(${Qt5Widgets_INCLUDE_DIRS}) add_subdirectory(depends/quazip) include_directories(depends/quazip) -# Add the java launcher +# Add the java launcher and checker add_subdirectory(depends/launcher) +add_subdirectory(depends/javacheck) # Add xz decompression add_subdirectory(depends/xz-embedded) @@ -84,10 +90,6 @@ IF(${BIGENDIAN}) 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) @@ -233,8 +235,6 @@ logic/BaseVersion.h logic/MinecraftVersion.h logic/InstanceFactory.h logic/InstanceFactory.cpp -logic/BaseUpdate.h -logic/BaseUpdate.cpp logic/BaseInstance.h logic/BaseInstance.cpp logic/BaseInstance_p.h @@ -258,6 +258,8 @@ logic/net/ByteArrayDownload.h logic/net/ByteArrayDownload.cpp logic/net/CacheDownload.h logic/net/CacheDownload.cpp +logic/net/ForgeMirrors.h +logic/net/ForgeMirrors.cpp logic/net/ForgeXzDownload.h logic/net/ForgeXzDownload.cpp logic/net/NetJob.h @@ -338,6 +340,8 @@ logic/tasks/Task.h logic/tasks/Task.cpp # Utilities +logic/JavaChecker.h +logic/JavaChecker.cpp logic/JavaUtils.h logic/JavaUtils.cpp logic/NagUtils.h @@ -408,20 +412,24 @@ IF(WIN32) ENDIF(WIN32) # Tell CMake that MultiMCLauncher.jar is generated. -SET_SOURCE_FILES_PROPERTIES(resources/MultiMCLauncher.jar GENERATED) +SET_SOURCE_FILES_PROPERTIES(${PROJECT_BINARY_DIR}/depends/launcher/MultiMCLauncher.jar GENERATED) +SET_SOURCE_FILES_PROPERTIES(${PROJECT_BINARY_DIR}/depends/javacheck/JavaCheck.jar GENERATED) # Qt 5 stuff QT5_WRAP_UI(MULTIMC_UI ${MULTIMC_UIS}) -QT5_ADD_RESOURCES(MULTIMC_QRC multimc.qrc) +CONFIGURE_FILE(generated.qrc.in generated.qrc) +QT5_ADD_RESOURCES(GENERATED_QRC ${CMAKE_CURRENT_BINARY_DIR}/generated.qrc) +QT5_ADD_RESOURCES(GRAPHICS_QRC graphics.qrc) + # Add executable ADD_EXECUTABLE(MultiMC MACOSX_BUNDLE WIN32 - ${MULTIMC_SOURCES} ${MULTIMC_UI} ${MULTIMC_QRC} ${MULTIMC_RCS}) + ${MULTIMC_SOURCES} ${MULTIMC_UI} ${GRAPHICS_QRC} ${GENERATED_QRC} ${MULTIMC_RCS}) # Link TARGET_LINK_LIBRARIES(MultiMC xz-embedded unpack200 quazip libUtil libSettings libGroupView ${MultiMC_LINK_ADDITIONAL_LIBS}) QT5_USE_MODULES(MultiMC Core Widgets Network Xml ${MultiMC_QT_ADDITIONAL_MODULES}) -ADD_DEPENDENCIES(MultiMC MultiMCLauncher) +ADD_DEPENDENCIES(MultiMC MultiMCLauncher JavaCheck) option(BUILD_KEYRING_TEST "Build the simple keyring test binary" OFF) IF(BUILD_KEYRING_TEST) @@ -579,3 +587,5 @@ endif (UPDATE_TRANSLATIONS) add_custom_target (translations DEPENDS ${QM_FILES}) install(FILES ${QM_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/translations) + + diff --git a/MultiMC.cpp b/MultiMC.cpp index 9179f0e0..17981755 100644 --- a/MultiMC.cpp +++ b/MultiMC.cpp @@ -328,8 +328,6 @@ void MultiMC::initGlobalSettings() // The cat m_settings->registerSetting(new Setting("TheCat", false)); - // Shall the main window hide on instance launch - m_settings->registerSetting(new Setting("NoHide", false)); m_settings->registerSetting(new Setting("InstSortMode", "Name")); @@ -345,6 +343,9 @@ void MultiMC::initGlobalSettings() // Window state and geometry m_settings->registerSetting(new Setting("MainWindowState", "")); m_settings->registerSetting(new Setting("MainWindowGeometry", "")); + + m_settings->registerSetting(new Setting("ConsoleWindowState", "")); + m_settings->registerSetting(new Setting("ConsoleWindowGeometry", "")); } void MultiMC::initHttpMetaCache() diff --git a/depends/launcher/UseJava.cmake b/cmake/UseJava.cmake index 1a5ef107..1a5ef107 100644 --- a/depends/launcher/UseJava.cmake +++ b/cmake/UseJava.cmake diff --git a/depends/launcher/UseJavaClassFilelist.cmake b/cmake/UseJavaClassFilelist.cmake index c842bf71..c842bf71 100644 --- a/depends/launcher/UseJavaClassFilelist.cmake +++ b/cmake/UseJavaClassFilelist.cmake diff --git a/depends/launcher/UseJavaSymlinks.cmake b/cmake/UseJavaSymlinks.cmake index c66ee1ea..c66ee1ea 100644 --- a/depends/launcher/UseJavaSymlinks.cmake +++ b/cmake/UseJavaSymlinks.cmake diff --git a/depends/javacheck/CMakeLists.txt b/depends/javacheck/CMakeLists.txt new file mode 100644 index 00000000..e72c9552 --- /dev/null +++ b/depends/javacheck/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 2.8.6) +project(launcher Java) +find_package(Java 1.6 REQUIRED COMPONENTS Development) + +include(UseJava) +set(CMAKE_JAVA_JAR_ENTRY_POINT JavaCheck) +set(CMAKE_JAVA_COMPILE_FLAGS -target 1.6 -source 1.6 -Xlint:deprecation -Xlint:unchecked) +#set(CMAKE_JAVA_TARGET_OUTPUT_DIR "${PROJECT_SOURCE_DIR}/../../resources") + +set(SRC + JavaCheck.java +) + +add_jar(JavaCheck ${SRC})
\ No newline at end of file diff --git a/depends/javacheck/JavaCheck.java b/depends/javacheck/JavaCheck.java new file mode 100644 index 00000000..73688082 --- /dev/null +++ b/depends/javacheck/JavaCheck.java @@ -0,0 +1,14 @@ +import java.lang.Integer; + +public class JavaCheck +{ + private static final String key = "os.arch"; + public static void main (String [] args) + { + String property = System.getProperty(key); + System.out.println(key + "=" + property); + if (property != null) + System.exit(0); + System.exit(1); + } +} diff --git a/depends/launcher/CMakeLists.txt b/depends/launcher/CMakeLists.txt index e5402ce7..e91d5bd6 100644 --- a/depends/launcher/CMakeLists.txt +++ b/depends/launcher/CMakeLists.txt @@ -1,13 +1,11 @@ cmake_minimum_required(VERSION 2.8.6) project(launcher Java) -set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}") find_package(Java 1.6 REQUIRED COMPONENTS Development) - include(UseJava) set(CMAKE_JAVA_JAR_ENTRY_POINT MultiMCLauncher) set(CMAKE_JAVA_COMPILE_FLAGS -target 1.6 -source 1.6 -Xlint:deprecation -Xlint:unchecked) -set(CMAKE_JAVA_TARGET_OUTPUT_DIR "${PROJECT_SOURCE_DIR}/../../resources") +#set(CMAKE_JAVA_TARGET_OUTPUT_DIR "${PROJECT_SOURCE_DIR}/../../resources") set(SRC MultiMCLauncher.java @@ -20,4 +18,4 @@ set(SRC MCFrame.java ) -add_jar(MultiMCLauncher ${SRC})
\ No newline at end of file +add_jar(MultiMCLauncher ${SRC}) diff --git a/generated.qrc.in b/generated.qrc.in new file mode 100644 index 00000000..82f4db99 --- /dev/null +++ b/generated.qrc.in @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/java"> + <file alias="launcher.jar">@MMC_BIN@/depends/launcher/MultiMCLauncher.jar</file> + <file alias="checker.jar">@MMC_BIN@/depends/javacheck/JavaCheck.jar</file> + </qresource> +</RCC> diff --git a/multimc.qrc b/graphics.qrc index 86f50b80..fe8892fe 100644 --- a/multimc.qrc +++ b/graphics.qrc @@ -40,9 +40,6 @@ <file alias="stone">resources/icons/instances/stone.png</file> <file alias="tnt">resources/icons/instances/tnt.png</file> </qresource> - <qresource prefix="/launcher"> - <file alias="launcher.jar">resources/MultiMCLauncher.jar</file> - </qresource> <qresource prefix="/icons/multimc"> <file alias="scalable/apps/multimc.svg">resources/icons/multimc.svg</file> <file alias="index.theme">resources/XdgIcon.theme</file> diff --git a/gui/ConsoleWindow.cpp b/gui/ConsoleWindow.cpp index ec25b9cf..d8a1b69d 100644 --- a/gui/ConsoleWindow.cpp +++ b/gui/ConsoleWindow.cpp @@ -15,6 +15,7 @@ #include "ConsoleWindow.h" #include "ui_ConsoleWindow.h" +#include "MultiMC.h" #include <QScrollBar> #include <QMessageBox> @@ -22,16 +23,27 @@ #include <gui/Platform.h> #include <gui/dialogs/CustomMessageBox.h> -ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent) : - QDialog(parent), - ui(new Ui::ConsoleWindow), - m_mayclose(true), - proc(mcproc) +ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent) + : QMainWindow(parent), ui(new Ui::ConsoleWindow), proc(mcproc) { MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); - this->setWindowFlags(Qt::Window); - connect(mcproc, SIGNAL(ended(BaseInstance*)), this, SLOT(onEnded(BaseInstance*))); + connect(mcproc, SIGNAL(log(QString, MessageLevel::Enum)), this, + SLOT(write(QString, MessageLevel::Enum))); + connect(mcproc, SIGNAL(ended(BaseInstance *, int, QProcess::ExitStatus)), this, + SLOT(onEnded(BaseInstance *, int, QProcess::ExitStatus))); + connect(mcproc, SIGNAL(prelaunch_failed(BaseInstance*,int,QProcess::ExitStatus)), this, + SLOT(onEnded(BaseInstance *, int, QProcess::ExitStatus))); + connect(mcproc, SIGNAL(launch_failed(BaseInstance*)), this, + SLOT(onLaunchFailed(BaseInstance*))); + + restoreState(QByteArray::fromBase64(MMC->settings()->get("ConsoleWindowState").toByteArray())); + restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("ConsoleWindowGeometry").toByteArray())); + + if (mcproc->instance()->settings().get("ShowConsole").toBool()) + { + show(); + } } ConsoleWindow::~ConsoleWindow() @@ -54,32 +66,32 @@ void ConsoleWindow::writeColor(QString text, const char *color) void ConsoleWindow::write(QString data, MessageLevel::Enum mode) { if (data.endsWith('\n')) - data = data.left(data.length()-1); + data = data.left(data.length() - 1); QStringList paragraphs = data.split('\n'); - for(QString ¶graph : paragraphs) + for (QString ¶graph : paragraphs) { paragraph = paragraph.trimmed(); } QListIterator<QString> iter(paragraphs); if (mode == MessageLevel::MultiMC) - while(iter.hasNext()) + while (iter.hasNext()) writeColor(iter.next(), "blue"); else if (mode == MessageLevel::Error) - while(iter.hasNext()) + while (iter.hasNext()) writeColor(iter.next(), "red"); else if (mode == MessageLevel::Warning) - while(iter.hasNext()) + while (iter.hasNext()) writeColor(iter.next(), "orange"); else if (mode == MessageLevel::Fatal) - while(iter.hasNext()) + while (iter.hasNext()) writeColor(iter.next(), "pink"); else if (mode == MessageLevel::Debug) - while(iter.hasNext()) + while (iter.hasNext()) writeColor(iter.next(), "green"); // TODO: implement other MessageLevels else - while(iter.hasNext()) + while (iter.hasNext()) writeColor(iter.next()); } @@ -102,34 +114,53 @@ void ConsoleWindow::setMayClose(bool mayclose) ui->closeButton->setEnabled(false); } -void ConsoleWindow::closeEvent(QCloseEvent * event) +void ConsoleWindow::closeEvent(QCloseEvent *event) { - if(!m_mayclose) + if (!m_mayclose) event->ignore(); else - QDialog::closeEvent(event); + { + MMC->settings()->set("ConsoleWindowState", saveState().toBase64()); + MMC->settings()->set("ConsoleWindowGeometry", saveGeometry().toBase64()); + + emit isClosing(); + QMainWindow::closeEvent(event); + } } void ConsoleWindow::on_btnKillMinecraft_clicked() { ui->btnKillMinecraft->setEnabled(false); - auto response = CustomMessageBox::selectable(this, tr("Kill Minecraft?"), - tr("This can cause the instance to get corrupted and should only be used if Minecraft is frozen for some reason"), - QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)->exec(); + auto response = CustomMessageBox::selectable( + this, tr("Kill Minecraft?"), + tr("This can cause the instance to get corrupted and should only be used if Minecraft " + "is frozen for some reason"), + QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)->exec(); if (response == QMessageBox::Yes) proc->killMinecraft(); else ui->btnKillMinecraft->setEnabled(true); } -void ConsoleWindow::onEnded(BaseInstance *instance) +void ConsoleWindow::onEnded(BaseInstance *instance, int code, QProcess::ExitStatus status) { ui->btnKillMinecraft->setEnabled(false); - // TODO: Might need an option to forcefully close, even on an error - if(instance->settings().get("AutoCloseConsole").toBool()) + if (instance->settings().get("AutoCloseConsole").toBool()) { - // TODO: Check why this doesn't work - if (!proc->exitCode()) this->close(); + if (code == 0 && status != QProcess::CrashExit) + { + this->close(); + return; + } } + if(!isVisible()) + show(); +} + +void ConsoleWindow::onLaunchFailed(BaseInstance *instance) +{ + ui->btnKillMinecraft->setEnabled(false); + if(!isVisible()) + show(); } diff --git a/gui/ConsoleWindow.h b/gui/ConsoleWindow.h index 0ed35554..e0a47bc6 100644 --- a/gui/ConsoleWindow.h +++ b/gui/ConsoleWindow.h @@ -15,7 +15,7 @@ #pragma once -#include <QDialog> +#include <QMainWindow> #include "logic/MinecraftProcess.h" namespace Ui @@ -23,7 +23,7 @@ namespace Ui class ConsoleWindow; } -class ConsoleWindow : public QDialog +class ConsoleWindow : public QMainWindow { Q_OBJECT @@ -38,6 +38,9 @@ public: */ void setMayClose(bool mayclose); +signals: + void isClosing(); + public slots: /** @@ -66,14 +69,17 @@ private slots: void on_closeButton_clicked(); void on_btnKillMinecraft_clicked(); - void onEnded(BaseInstance *instance); + void onEnded(BaseInstance *instance, int code, QProcess::ExitStatus status); + void onLaunchFailed(BaseInstance *instance); + + // FIXME: add handlers for the other MinecraftProcess signals (pre/post launch command + // failures) protected: void closeEvent(QCloseEvent *); private: - Ui::ConsoleWindow *ui; - MinecraftProcess *proc; - bool m_mayclose; + Ui::ConsoleWindow *ui = nullptr; + MinecraftProcess *proc = nullptr; + bool m_mayclose = true; }; - diff --git a/gui/ConsoleWindow.ui b/gui/ConsoleWindow.ui index 472c7c8d..ed1b627b 100644 --- a/gui/ConsoleWindow.ui +++ b/gui/ConsoleWindow.ui @@ -1,99 +1,84 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>ConsoleWindow</class> - <widget class="QDialog" name="ConsoleWindow"> + <widget class="QMainWindow" name="ConsoleWindow"> <property name="geometry"> <rect> <x>0</x> <y>0</y> - <width>610</width> - <height>391</height> + <width>640</width> + <height>440</height> </rect> </property> <property name="windowTitle"> <string>MultiMC Console</string> </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>6</number> - </property> - <item> - <widget class="QPlainTextEdit" name="text"> - <property name="font"> - <font> - <pointsize>10</pointsize> - </font> - </property> - <property name="undoRedoEnabled"> - <bool>false</bool> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - <property name="plainText"> - <string notr="true"/> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - <property name="centerOnScroll"> - <bool>false</bool> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <property name="leftMargin"> - <number>6</number> - </property> - <property name="rightMargin"> - <number>6</number> - </property> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="btnKillMinecraft"> - <property name="text"> - <string>&Kill Minecraft</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="closeButton"> - <property name="text"> - <string>&Close</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> + <widget class="QWidget" name="centralwidget"> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QPlainTextEdit" name="text"> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="undoRedoEnabled"> + <bool>false</bool> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="plainText"> + <string notr="true"/> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + <property name="centerOnScroll"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="leftMargin"> + <number>6</number> + </property> + <property name="rightMargin"> + <number>6</number> + </property> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="btnKillMinecraft"> + <property name="text"> + <string>&Kill Minecraft</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="closeButton"> + <property name="text"> + <string>&Close</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> </widget> - <tabstops> - <tabstop>text</tabstop> - <tabstop>closeButton</tabstop> - <tabstop>btnKillMinecraft</tabstop> - </tabstops> <resources/> <connections/> </ui> diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index 7ea67764..6ae41f50 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -127,8 +127,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi view->installEventFilter(this); proxymodel = new InstanceProxyModel(this); -// proxymodel->setSortRole(KCategorizedSortFilterProxyModel::CategorySortRole); - //proxymodel->setFilterRole(KCategorizedSortFilterProxyModel::CategorySortRole); + // proxymodel->setSortRole(KCategorizedSortFilterProxyModel::CategorySortRole); + // proxymodel->setFilterRole(KCategorizedSortFilterProxyModel::CategorySortRole); // proxymodel->setDynamicSortFilter ( true ); // FIXME: instList should be global-ish, or at least not tied to the main window... @@ -176,6 +176,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi { MMC->lwjgllist()->loadList(); } + assets_downloader = new OneSixAssets(); connect(assets_downloader, SIGNAL(indexStarted()), SLOT(assetsIndexStarted())); connect(assets_downloader, SIGNAL(filesStarted()), SLOT(assetsFilesStarted())); @@ -418,7 +419,7 @@ void MainWindow::on_actionSettings_triggered() { SettingsDialog dialog(this); dialog.exec(); - //FIXME: quick HACK to make this work. improve, optimize. + // FIXME: quick HACK to make this work. improve, optimize. proxymodel->invalidate(); proxymodel->sort(0); } @@ -598,7 +599,7 @@ void MainWindow::doLogin(const QString &errorMsg) void MainWindow::prepareLaunch(BaseInstance* instance, MojangAccountPtr account) { - BaseUpdate *updateTask = instance->doUpdate(); + Task *updateTask = instance->doUpdate(); if (!updateTask) { launchInstance(instance, account); @@ -606,7 +607,7 @@ void MainWindow::prepareLaunch(BaseInstance* instance, MojangAccountPtr account) else { ProgressDialog tDialog(this); - connect(updateTask, &BaseUpdate::succeeded, [this, instance, account] { launchInstance(instance, account); }); + connect(updateTask, &Task::succeeded, [this, instance, account] { launchInstance(instance, account); }); connect(updateTask, SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString))); tDialog.exec(updateTask); delete updateTask; @@ -667,29 +668,15 @@ void MainWindow::launchInstance(BaseInstance *instance, MojangAccountPtr account if (!proc) return; - // Prepare GUI: If it shall stay open disable the required parts - if (MMC->settings()->get("NoHide").toBool()) - { - ui->actionLaunchInstance->setEnabled(false); - } - else - { - this->hide(); - } + this->hide(); console = new ConsoleWindow(proc); - - connect(proc, SIGNAL(log(QString, MessageLevel::Enum)), console, - SLOT(write(QString, MessageLevel::Enum))); - connect(proc, SIGNAL(ended(BaseInstance *)), this, SLOT(instanceEnded(BaseInstance *))); - - if (instance->settings().get("ShowConsole").toBool()) - { - console->show(); - } + connect(console, SIGNAL(isClosing()), this, SLOT(instanceEnded())); // I think this will work... - proc->setLogin(account->username(), account->accessToken()); + QString username = account->username(); + QString session_id = account->accessToken(); + proc->setLogin(username, session_id); proc->launch(); } @@ -845,15 +832,9 @@ void MainWindow::on_actionEditInstNotes_triggered() } } -void MainWindow::instanceEnded(BaseInstance *instance) +void MainWindow::instanceEnded() { this->show(); - ui->actionLaunchInstance->setEnabled(m_selectedInstance); - - if (instance->settings().get("AutoCloseConsole").toBool()) - { - console->close(); - } } void MainWindow::checkSetDefaultJava() diff --git a/gui/MainWindow.h b/gui/MainWindow.h index f88905bf..3b8d4668 100644 --- a/gui/MainWindow.h +++ b/gui/MainWindow.h @@ -16,6 +16,7 @@ #pragma once #include <QMainWindow> +#include <QProcess> #include "logic/lists/InstanceList.h" #include "logic/net/LoginTask.h" @@ -125,7 +126,7 @@ slots: void on_actionChangeInstLWJGLVersion_triggered(); - void instanceEnded(BaseInstance *instance); + void instanceEnded(); void on_actionInstanceSettings_triggered(); diff --git a/gui/dialogs/AboutDialog.ui b/gui/dialogs/AboutDialog.ui index 0a189d9c..f674eb61 100644 --- a/gui/dialogs/AboutDialog.ui +++ b/gui/dialogs/AboutDialog.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>450</width> - <height>429</height> + <width>637</width> + <height>579</height> </rect> </property> <property name="minimumSize"> @@ -59,7 +59,7 @@ <string/> </property> <property name="pixmap"> - <pixmap resource="../../multimc.qrc">:/icons/multimc/scalable/apps/multimc.svg</pixmap> + <pixmap resource="../../graphics.qrc">:/icons/multimc/scalable/apps/multimc.svg</pixmap> </property> </widget> </item> @@ -100,8 +100,8 @@ <rect> <x>0</x> <y>0</y> - <width>432</width> - <height>179</height> + <width>619</width> + <height>329</height> </rect> </property> <attribute name="label"> @@ -159,8 +159,8 @@ <rect> <x>0</x> <y>0</y> - <width>98</width> - <height>120</height> + <width>619</width> + <height>329</height> </rect> </property> <attribute name="label"> @@ -203,8 +203,8 @@ p, li { white-space: pre-wrap; } <rect> <x>0</x> <y>0</y> - <width>98</width> - <height>88</height> + <width>619</width> + <height>329</height> </rect> </property> <attribute name="label"> @@ -227,6 +227,7 @@ p, li { white-space: pre-wrap; } <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; font-weight:600;">MultiMC</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">Copyright 2012 MultiMC Contributors</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">you may not use this file except in compliance with the License.</span></p> @@ -240,31 +241,124 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">See the License for the specific language governing permissions and</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">limitations under the License.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:10pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">MultiMC uses QSLog, </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">Copyright (c) 2010, Razvan Petru</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">All rights reserved.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:10pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">Redistribution and use in source and binary forms, with or without modification,</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">are permitted provided that the following conditions are met:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:10pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">* Redistributions of source code must retain the above copyright notice, this</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;"> list of conditions and the following disclaimer.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">* Redistributions in binary form must reproduce the above copyright notice, this</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;"> list of conditions and the following disclaimer in the documentation and/or other</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;"> materials provided with the distribution.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">* The name of the contributors may not be used to endorse or promote products</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;"> derived from this software without specific prior written permission.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:10pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot; AND</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">OF THE POSSIBILITY OF SUCH DAMAGE.</span></p></body></html></string> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; font-weight:600;">QSLog</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Copyright (c) 2010, Razvan Petru</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">All rights reserved.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Redistribution and use in source and binary forms, with or without modification,</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">are permitted provided that the following conditions are met:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">* Redistributions of source code must retain the above copyright notice, this</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> list of conditions and the following disclaimer.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">* Redistributions in binary form must reproduce the above copyright notice, this</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> list of conditions and the following disclaimer in the documentation and/or other</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> materials provided with the distribution.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">* The name of the contributors may not be used to endorse or promote products</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> derived from this software without specific prior written permission.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot; AND</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">OF THE POSSIBILITY OF SUCH DAMAGE.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; font-weight:600;">Group View (instance view)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">/**</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Copyright (C) 2007 Rafael Fernández López &lt;ereslibre@kde.org&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Copyright (C) 2007 John Tapsell &lt;tapsell@kde.org&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> *</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * This library is free software; you can redistribute it and/or</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * modify it under the terms of the GNU Library General Public</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * License as published by the Free Software Foundation; either</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * version 2 of the License, or (at your option) any later version.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> *</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * This library is distributed in the hope that it will be useful,</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * but WITHOUT ANY WARRANTY; without even the implied warranty of</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Library General Public License for more details.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> *</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * You should have received a copy of the GNU Library General Public License</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * along with this library; see the file COPYING.LIB. If not, write to</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Boston, MA 02110-1301, USA.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> */</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; font-weight:600;">Pack200</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The GNU General Public License (GPL)</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Version 2, June 1991</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">+ &quot;CLASSPATH&quot; EXCEPTION TO THE GPL</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Certain source files distributed by Oracle America and/or its affiliates are</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">subject to the following clarification and special exception to the GPL, but</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">only where Oracle has expressly included in the particular source file's header</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">the words &quot;Oracle designates this particular file as subject to the &quot;Classpath&quot;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">exception as provided by Oracle in the LICENSE file that accompanied this code.&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> Linking this library statically or dynamically with other modules is making</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> a combined work based on this library. Thus, the terms and conditions of</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> the GNU General Public License cover the whole combination.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> As a special exception, the copyright holders of this library give you</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> permission to link this library with independent modules to produce an</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> executable, regardless of the license terms of these independent modules,</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> and to copy and distribute the resulting executable under terms of your</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> choice, provided that you also meet, for each linked independent module,</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> the terms and conditions of the license of that module. An independent</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> module is a module which is not derived from or based on this library. If</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> you modify this library, you may extend this exception to your version of</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> the library, but you are not obligated to do so. If you do not wish to do</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> so, delete this exception statement from your version.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; font-weight:600;">Quazip</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Copyright (C) 2005-2011 Sergey A. Tachenov</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">This program is free software; you can redistribute it and/or modify it</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">under the terms of the GNU Lesser General Public License as published by</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">the Free Software Foundation; either version 2 of the License, or (at</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">your option) any later version.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">This program is distributed in the hope that it will be useful, but</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">WITHOUT ANY WARRANTY; without even the implied warranty of</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">General Public License for more details.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">You should have received a copy of the GNU Lesser General Public License</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">along with this program; if not, write to the Free Software Foundation,</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">See COPYING file for the full LGPL text.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Original ZIP package is copyrighted by Gilles Vollant, see</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">quazip/(un)zip.h files for details, basically it's zlib license.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; font-weight:600;">xz-minidec</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">/*</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * XZ decompressor</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> *</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Authors: Lasse Collin &lt;lasse.collin@tukaani.org&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Igor Pavlov &lt;http://7-zip.org/&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> *</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * This file has been put into the public domain.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * You can do whatever you want with this file.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> */</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p></body></html></string> </property> </widget> </item> @@ -309,8 +403,8 @@ p, li { white-space: pre-wrap; } </layout> </widget> <resources> - <include location="../../multimc.qrc"/> - <include location="../../multimc.qrc"/> + <include location="../../graphics.qrc"/> + <include location="../../graphics.qrc"/> </resources> <connections/> </ui> diff --git a/gui/dialogs/CopyInstanceDialog.ui b/gui/dialogs/CopyInstanceDialog.ui index dd7ce641..4aa1cb27 100644 --- a/gui/dialogs/CopyInstanceDialog.ui +++ b/gui/dialogs/CopyInstanceDialog.ui @@ -17,7 +17,7 @@ <string>Copy Instance</string> </property> <property name="windowIcon"> - <iconset resource="../../multimc.qrc"> + <iconset resource="../../graphics.qrc"> <normaloff>:/icons/toolbar/copy</normaloff>:/icons/toolbar/copy</iconset> </property> <property name="modal"> @@ -42,7 +42,7 @@ <item> <widget class="QToolButton" name="iconButton"> <property name="icon"> - <iconset resource="../../multimc.qrc"> + <iconset resource="../../graphics.qrc"> <normaloff>:/icons/instances/infinity</normaloff>:/icons/instances/infinity</iconset> </property> <property name="iconSize"> @@ -95,7 +95,7 @@ </layout> </widget> <resources> - <include location="../../multimc.qrc"/> + <include location="../../graphics.qrc"/> </resources> <connections> <connection> diff --git a/gui/dialogs/LoginDialog.ui b/gui/dialogs/LoginDialog.ui index d15679dd..45f319ed 100644 --- a/gui/dialogs/LoginDialog.ui +++ b/gui/dialogs/LoginDialog.ui @@ -50,7 +50,7 @@ <string/> </property> <property name="pixmap"> - <pixmap resource="../../multimc.qrc">:/icons/instances/steve</pixmap> + <pixmap resource="../../graphics.qrc">:/icons/instances/steve</pixmap> </property> <property name="scaledContents"> <bool>true</bool> @@ -146,7 +146,7 @@ </layout> </widget> <resources> - <include location="../../multimc.qrc"/> + <include location="../../graphics.qrc"/> <include location="../multimc.qrc"/> </resources> <connections> diff --git a/gui/dialogs/NewInstanceDialog.ui b/gui/dialogs/NewInstanceDialog.ui index b4b8723e..00544463 100644 --- a/gui/dialogs/NewInstanceDialog.ui +++ b/gui/dialogs/NewInstanceDialog.ui @@ -17,7 +17,7 @@ <string>New Instance</string> </property> <property name="windowIcon"> - <iconset resource="../../multimc.qrc"> + <iconset resource="../../graphics.qrc"> <normaloff>:/icons/toolbar/new</normaloff>:/icons/toolbar/new</iconset> </property> <property name="modal"> @@ -42,7 +42,7 @@ <item> <widget class="QToolButton" name="iconButton"> <property name="icon"> - <iconset resource="../../multimc.qrc"> + <iconset resource="../../graphics.qrc"> <normaloff>:/icons/instances/infinity</normaloff>:/icons/instances/infinity</iconset> </property> <property name="iconSize"> @@ -140,7 +140,7 @@ </layout> </widget> <resources> - <include location="../../multimc.qrc"/> + <include location="../../graphics.qrc"/> </resources> <connections> <connection> diff --git a/gui/dialogs/SettingsDialog.cpp b/gui/dialogs/SettingsDialog.cpp index e4f22d83..57e15a5b 100644 --- a/gui/dialogs/SettingsDialog.cpp +++ b/gui/dialogs/SettingsDialog.cpp @@ -25,6 +25,7 @@ #include "logic/JavaUtils.h" #include "logic/NagUtils.h" #include "logic/lists/JavaVersionList.h" +#include <logic/JavaChecker.h> #include <settingsobject.h> #include <pathutils.h> @@ -98,12 +99,6 @@ void SettingsDialog::on_lwjglDirBrowseBtn_clicked() } } -void SettingsDialog::on_compatModeCheckBox_clicked(bool checked) -{ - Q_UNUSED(checked); - updateCheckboxStuff(); -} - void SettingsDialog::on_maximizedCheckBox_clicked(bool checked) { Q_UNUSED(checked); @@ -235,7 +230,7 @@ void SettingsDialog::loadSettings(SettingsObject *s) ui->postExitCmdTextBox->setText(s->get("PostExitCommand").toString()); } -void SettingsDialog::on_pushButton_clicked() +void SettingsDialog::on_javaDetectBtn_clicked() { JavaVersionPtr java; @@ -250,7 +245,7 @@ void SettingsDialog::on_pushButton_clicked() } } -void SettingsDialog::on_btnBrowse_clicked() +void SettingsDialog::on_javaBrowseBtn_clicked() { QString dir = QFileDialog::getOpenFileName(this, tr("Find Java executable")); if (!dir.isNull()) @@ -258,3 +253,32 @@ void SettingsDialog::on_btnBrowse_clicked() ui->javaPathTextBox->setText(dir); } } + +void SettingsDialog::on_javaTestBtn_clicked() +{ + checker.reset(new JavaChecker()); + connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this, + SLOT(checkFinished(JavaCheckResult))); + checker->performCheck(ui->javaPathTextBox->text()); +} + +void SettingsDialog::checkFinished(JavaCheckResult result) +{ + if (result.valid) + { + QString text; + text += "Java test succeeded!\n"; + if (result.is_64bit) + text += "Using 64bit java.\n"; + text += "\n"; + text += "Platform reported: " + result.realPlatform; + QMessageBox::information(this, tr("Java test success"), text); + } + else + { + QMessageBox::information( + this, tr("Java test failure"), + tr("The specified java binary didn't work. You should use the auto-detect feature, " + "or set the path to the java executable.")); + } +} diff --git a/gui/dialogs/SettingsDialog.h b/gui/dialogs/SettingsDialog.h index e24047c3..0cb8fa38 100644 --- a/gui/dialogs/SettingsDialog.h +++ b/gui/dialogs/SettingsDialog.h @@ -15,8 +15,11 @@ #pragma once +#include <memory> #include <QDialog> +#include "logic/JavaChecker.h" + class SettingsObject; namespace Ui @@ -48,16 +51,18 @@ slots: void on_lwjglDirBrowseBtn_clicked(); - void on_compatModeCheckBox_clicked(bool checked); - void on_maximizedCheckBox_clicked(bool checked); void on_buttonBox_accepted(); - void on_pushButton_clicked(); + void on_javaDetectBtn_clicked(); + + void on_javaTestBtn_clicked(); - void on_btnBrowse_clicked(); + void on_javaBrowseBtn_clicked(); + void checkFinished(JavaCheckResult result); private: Ui::SettingsDialog *ui; + std::shared_ptr<JavaChecker> checker; }; diff --git a/gui/dialogs/SettingsDialog.ui b/gui/dialogs/SettingsDialog.ui index 53a41d6e..6a44a631 100644 --- a/gui/dialogs/SettingsDialog.ui +++ b/gui/dialogs/SettingsDialog.ui @@ -6,7 +6,7 @@ <rect> <x>0</x> <y>0</y> - <width>502</width> + <width>526</width> <height>599</height> </rect> </property> @@ -20,7 +20,7 @@ <string>Settings</string> </property> <property name="windowIcon"> - <iconset resource="../../multimc.qrc"> + <iconset resource="../../graphics.qrc"> <normaloff>:/icons/toolbar/settings</normaloff>:/icons/toolbar/settings</iconset> </property> <property name="modal"> @@ -407,8 +407,14 @@ </property> </widget> </item> - <item row="1" column="3"> - <widget class="QPushButton" name="btnBrowse"> + <item row="0" column="1" colspan="5"> + <widget class="QLineEdit" name="javaPathTextBox"/> + </item> + <item row="2" column="1" colspan="5"> + <widget class="QLineEdit" name="jvmArgsTextBox"/> + </item> + <item row="1" column="5"> + <widget class="QPushButton" name="javaTestBtn"> <property name="sizePolicy"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <horstretch>0</horstretch> @@ -416,15 +422,25 @@ </sizepolicy> </property> <property name="text"> - <string>Browse...</string> + <string>Test</string> </property> </widget> </item> - <item row="0" column="1" colspan="3"> - <widget class="QLineEdit" name="javaPathTextBox"/> + <item row="1" column="4"> + <widget class="QPushButton" name="javaBrowseBtn"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Browse...</string> + </property> + </widget> </item> - <item row="1" column="2"> - <widget class="QPushButton" name="pushButton"> + <item row="1" column="3"> + <widget class="QPushButton" name="javaDetectBtn"> <property name="sizePolicy"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <horstretch>0</horstretch> @@ -436,9 +452,6 @@ </property> </widget> </item> - <item row="2" column="1" colspan="3"> - <widget class="QLineEdit" name="jvmArgsTextBox"/> - </item> </layout> </widget> </item> @@ -528,14 +541,12 @@ <tabstop>maxMemSpinBox</tabstop> <tabstop>permGenSpinBox</tabstop> <tabstop>javaPathTextBox</tabstop> - <tabstop>pushButton</tabstop> - <tabstop>btnBrowse</tabstop> <tabstop>jvmArgsTextBox</tabstop> <tabstop>preLaunchCmdTextBox</tabstop> <tabstop>postExitCmdTextBox</tabstop> </tabstops> <resources> - <include location="../../multimc.qrc"/> + <include location="../../graphics.qrc"/> </resources> <connections> <connection> diff --git a/logic/BaseInstance.h b/logic/BaseInstance.h index b92d50cc..cf86fda6 100644 --- a/logic/BaseInstance.h +++ b/logic/BaseInstance.h @@ -25,7 +25,7 @@ #include "logic/auth/MojangAccount.h" class QDialog; -class BaseUpdate; +class Task; class MinecraftProcess; class OneSixUpdate; class InstanceList; @@ -151,7 +151,7 @@ public: virtual SettingsObject &settings() const; /// returns a valid update task if update is needed, NULL otherwise - virtual BaseUpdate *doUpdate() = 0; + virtual Task *doUpdate() = 0; /// returns a valid minecraft process, ready for launch with the given account. virtual MinecraftProcess *prepareForLaunch(MojangAccountPtr account) = 0; diff --git a/logic/BaseUpdate.cpp b/logic/BaseUpdate.cpp deleted file mode 100644 index 5aeb12ef..00000000 --- a/logic/BaseUpdate.cpp +++ /dev/null @@ -1,26 +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 "BaseUpdate.h" - -BaseUpdate::BaseUpdate(BaseInstance *inst, QObject *parent) : Task(parent) -{ - m_inst = inst; -} - -void BaseUpdate::updateDownloadProgress(qint64 current, qint64 total) -{ - emit progress(current, total); -}
\ No newline at end of file diff --git a/logic/BaseUpdate.h b/logic/BaseUpdate.h deleted file mode 100644 index ddeefa97..00000000 --- a/logic/BaseUpdate.h +++ /dev/null @@ -1,47 +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. - */ - -#pragma once - -#include <QObject> -#include <QList> -#include <QUrl> - -#include "net/NetJob.h" - -#include "tasks/Task.h" - -class MinecraftVersion; -class BaseInstance; - -/*! - * The game update task is the task that handles downloading instances' files. - */ -class BaseUpdate : public Task -{ - Q_OBJECT -public: - explicit BaseUpdate(BaseInstance *inst, QObject *parent = 0); - - virtual void executeTask() = 0; - -protected -slots: - // virtual void error(const QString &msg); - void updateDownloadProgress(qint64 current, qint64 total); - -protected: - BaseInstance *m_inst; -}; diff --git a/logic/InstanceLauncher.cpp b/logic/InstanceLauncher.cpp index c4df8220..0ef0f045 100644 --- a/logic/InstanceLauncher.cpp +++ b/logic/InstanceLauncher.cpp @@ -50,12 +50,9 @@ void InstanceLauncher::onLoginComplete() return; } console = new ConsoleWindow(proc); - console->show(); - - connect(proc, SIGNAL(ended()), SLOT(onTerminated())); - connect(proc, SIGNAL(log(QString, MessageLevel::Enum)), console, - SLOT(write(QString, MessageLevel::Enum))); + connect(console, SIGNAL(isClosing()), this, SLOT(onTerminated())); + proc->setLogin(result.username, result.session_id); proc->launch(); */ } @@ -66,7 +63,7 @@ void InstanceLauncher::doLogin(const QString &errorMsg) loginDlg->exec(); if (loginDlg->result() == QDialog::Accepted) { - UserInfo uInfo{loginDlg->getUsername(), loginDlg->getPassword()}; + PasswordLogin uInfo{loginDlg->getUsername(), loginDlg->getPassword()}; ProgressDialog *tDialog = new ProgressDialog(nullptr); LoginTask *loginTask = new LoginTask(uInfo, tDialog); diff --git a/logic/JavaChecker.cpp b/logic/JavaChecker.cpp new file mode 100644 index 00000000..10b84fe1 --- /dev/null +++ b/logic/JavaChecker.cpp @@ -0,0 +1,89 @@ +#include "JavaChecker.h" +#include <QFile> +#include <QProcess> + +#define CHECKER_FILE "JavaChecker.jar" + +JavaChecker::JavaChecker(QObject *parent) : QObject(parent) +{ +} + +int JavaChecker::performCheck(QString path) +{ + if(QFile::exists(CHECKER_FILE)) + { + QFile::remove(CHECKER_FILE); + } + // extract the checker + QFile(":/java/checker.jar").copy(CHECKER_FILE); + + QStringList args = {"-jar", CHECKER_FILE}; + + process.reset(new QProcess()); + process->setArguments(args); + process->setProgram(path); + process->setProcessChannelMode(QProcess::SeparateChannels); + + connect(process.get(), SIGNAL(finished(int, QProcess::ExitStatus)), this, + SLOT(finished(int, QProcess::ExitStatus))); + connect(process.get(), SIGNAL(error(QProcess::ProcessError)), this, + SLOT(error(QProcess::ProcessError))); + connect(&killTimer, SIGNAL(timeout()), SLOT(timeout())); + killTimer.setSingleShot(true); + killTimer.start(5000); + process->start(); +} + +void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) +{ + killTimer.stop(); + QProcessPtr _process; + _process.swap(process); + + if (status == QProcess::CrashExit || exitcode == 1) + { + emit checkFinished({}); + return; + } + + QString p_stdout = _process->readAllStandardOutput(); + auto parts = p_stdout.split('=', QString::SkipEmptyParts); + if (parts.size() != 2 || parts[0] != "os.arch") + { + emit checkFinished({}); + return; + } + + auto os_arch = parts[1].remove('\n').remove('\r'); + bool is_64 = os_arch == "x86_64" || os_arch == "amd64"; + + JavaCheckResult result; + { + result.valid = true; + result.is_64bit = is_64; + result.mojangPlatform = is_64 ? "64" : "32"; + result.realPlatform = os_arch; + } + emit checkFinished(result); +} + +void JavaChecker::error(QProcess::ProcessError err) +{ + if(err == QProcess::FailedToStart) + { + killTimer.stop(); + emit checkFinished({}); + return; + } +} + +void JavaChecker::timeout() +{ + // NO MERCY. NO ABUSE. + if(process) + { + process->kill(); + process.reset(); + emit checkFinished({}); + } +} diff --git a/logic/JavaChecker.h b/logic/JavaChecker.h new file mode 100644 index 00000000..60f8b56f --- /dev/null +++ b/logic/JavaChecker.h @@ -0,0 +1,32 @@ +#pragma once +#include <QProcess> +#include <QTimer> +#include <memory> + +struct JavaCheckResult +{ + QString mojangPlatform; + QString realPlatform; + bool valid = false; + bool is_64bit = false; +}; +typedef std::shared_ptr<QProcess> QProcessPtr; + +class JavaChecker : public QObject +{ + Q_OBJECT +public: + explicit JavaChecker(QObject *parent = 0); + int performCheck(QString path); + +signals: + void checkFinished(JavaCheckResult result); +private: + QProcessPtr process; + QTimer killTimer; +public +slots: + void timeout(); + void finished(int exitcode, QProcess::ExitStatus); + void error(QProcess::ProcessError); +}; diff --git a/logic/JavaUtils.h b/logic/JavaUtils.h index 8d7550d0..44f576b4 100644 --- a/logic/JavaUtils.h +++ b/logic/JavaUtils.h @@ -33,7 +33,6 @@ public: QList<JavaVersionPtr> FindJavaPaths(); JavaVersionPtr GetDefaultJava(); - private: #if WINDOWS diff --git a/logic/LegacyInstance.cpp b/logic/LegacyInstance.cpp index 3a337140..ab6536d0 100644 --- a/logic/LegacyInstance.cpp +++ b/logic/LegacyInstance.cpp @@ -44,7 +44,7 @@ LegacyInstance::LegacyInstance(const QString &rootDir, SettingsObject *settings, settings->registerSetting(new Setting("IntendedJarVersion", "")); } -BaseUpdate *LegacyInstance::doUpdate() +Task *LegacyInstance::doUpdate() { auto list = jarModList(); return new LegacyUpdate(this, this); @@ -59,7 +59,7 @@ MinecraftProcess *LegacyInstance::prepareForLaunch(MojangAccountPtr account) pixmap.save(PathCombine(minecraftRoot(), "icon.png"), "PNG"); // extract the legacy launcher - QFile(":/launcher/launcher.jar").copy(PathCombine(minecraftRoot(), LAUNCHER_FILE)); + QFile(":/java/launcher.jar").copy(PathCombine(minecraftRoot(), LAUNCHER_FILE)); // set the process arguments { @@ -104,15 +104,15 @@ MinecraftProcess *LegacyInstance::prepareForLaunch(MojangAccountPtr account) args << "-jar" << LAUNCHER_FILE; args << account->currentProfile()->name(); - args << account->accessToken(); + args << account->sessionId(); args << windowTitle; args << windowSize; args << lwjgl; - proc->setMinecraftArguments(args); + proc->setArguments(args); } // set the process work path - proc->setMinecraftWorkdir(minecraftRoot()); + proc->setWorkdir(minecraftRoot()); return proc; } @@ -227,56 +227,18 @@ QString LegacyInstance::instanceConfigFolder() const return PathCombine(minecraftRoot(), "config"); } -/* -bool LegacyInstance::shouldUpdateCurrentVersion() const -{ - QFileInfo jar(runnableJar()); - return jar.lastModified().toUTC().toMSecsSinceEpoch() != lastCurrentVersionUpdate(); -} - -void LegacyInstance::updateCurrentVersion(bool keepCurrent) -{ - QFileInfo jar(runnableJar()); - - if(!jar.exists()) - { - setLastCurrentVersionUpdate(0); - setCurrentVersionId("Unknown"); - return; - } - - qint64 time = jar.lastModified().toUTC().toMSecsSinceEpoch(); - - setLastCurrentVersionUpdate(time); - if (!keepCurrent) - { - // TODO: Implement GetMinecraftJarVersion function. - QString newVersion = -"Unknown";//javautils::GetMinecraftJarVersion(jar.absoluteFilePath()); - setCurrentVersionId(newVersion); - } -} -qint64 LegacyInstance::lastCurrentVersionUpdate() const -{ - I_D(LegacyInstance); - return d->m_settings->get ( "lastVersionUpdate" ).value<qint64>(); -} -void LegacyInstance::setLastCurrentVersionUpdate ( qint64 val ) -{ - I_D(LegacyInstance); - d->m_settings->set ( "lastVersionUpdate", val ); -} -*/ bool LegacyInstance::shouldRebuild() const { I_D(LegacyInstance); return d->m_settings->get("NeedsRebuild").toBool(); } + void LegacyInstance::setShouldRebuild(bool val) { I_D(LegacyInstance); d->m_settings->set("NeedsRebuild", val); } + QString LegacyInstance::currentVersionId() const { I_D(LegacyInstance); @@ -294,22 +256,26 @@ QString LegacyInstance::lwjglVersion() const I_D(LegacyInstance); return d->m_settings->get("LwjglVersion").toString(); } + void LegacyInstance::setLWJGLVersion(QString val) { I_D(LegacyInstance); d->m_settings->set("LwjglVersion", val); } + QString LegacyInstance::intendedVersionId() const { I_D(LegacyInstance); return d->m_settings->get("IntendedJarVersion").toString(); } + bool LegacyInstance::setIntendedVersionId(QString version) { settings().set("IntendedJarVersion", version); setShouldUpdate(true); return true; } + bool LegacyInstance::shouldUpdate() const { I_D(LegacyInstance); @@ -320,6 +286,7 @@ bool LegacyInstance::shouldUpdate() const } return true; } + void LegacyInstance::setShouldUpdate(bool val) { settings().set("ShouldUpdate", val); diff --git a/logic/LegacyInstance.h b/logic/LegacyInstance.h index e78bfd73..3d35521e 100644 --- a/logic/LegacyInstance.h +++ b/logic/LegacyInstance.h @@ -18,7 +18,7 @@ #include "BaseInstance.h" class ModList; -class BaseUpdate; +class Task; class LegacyInstance : public BaseInstance { @@ -78,7 +78,7 @@ public: virtual bool shouldUpdate() const; virtual void setShouldUpdate(bool val); - virtual BaseUpdate *doUpdate(); + virtual Task *doUpdate(); virtual MinecraftProcess *prepareForLaunch(MojangAccountPtr account); virtual void cleanupAfterRun(); diff --git a/logic/LegacyUpdate.cpp b/logic/LegacyUpdate.cpp index 8ba97827..05442917 100644 --- a/logic/LegacyUpdate.cpp +++ b/logic/LegacyUpdate.cpp @@ -26,7 +26,7 @@ #include <JlCompress.h> #include "logger/QsLog.h" -LegacyUpdate::LegacyUpdate(BaseInstance *inst, QObject *parent) : BaseUpdate(inst, parent) +LegacyUpdate::LegacyUpdate(BaseInstance *inst, QObject *parent) : Task(parent), m_inst(inst) { } diff --git a/logic/LegacyUpdate.h b/logic/LegacyUpdate.h index b30fa0b3..8ffdb0f0 100644 --- a/logic/LegacyUpdate.h +++ b/logic/LegacyUpdate.h @@ -21,14 +21,13 @@ #include "logic/net/NetJob.h" #include "logic/tasks/Task.h" -#include "logic/BaseUpdate.h" class MinecraftVersion; class BaseInstance; class QuaZip; class Mod; -class LegacyUpdate : public BaseUpdate +class LegacyUpdate : public Task { Q_OBJECT public: @@ -72,4 +71,5 @@ private: private: NetJobPtr legacyDownloadJob; + BaseInstance *m_inst; }; diff --git a/logic/MinecraftProcess.cpp b/logic/MinecraftProcess.cpp index ff122628..e4a26054 100644 --- a/logic/MinecraftProcess.cpp +++ b/logic/MinecraftProcess.cpp @@ -59,12 +59,12 @@ MinecraftProcess::MinecraftProcess(BaseInstance *inst) : m_instance(inst) connect(this, SIGNAL(readyReadStandardOutput()), SLOT(on_stdOut())); } -void MinecraftProcess::setMinecraftArguments(QStringList args) +void MinecraftProcess::setArguments(QStringList args) { m_args = args; } -void MinecraftProcess::setMinecraftWorkdir(QString path) +void MinecraftProcess::setWorkdir(QString path) { QDir mcDir(path); this->setWorkingDirectory(mcDir.absolutePath()); @@ -101,7 +101,7 @@ void MinecraftProcess::on_stdOut() for (int i = 0; i < lines.size() - 1; i++) { QString &line = lines[i]; - emit log(line /*.replace(username, "<Username>").replace(sessionID, "<Session ID>")*/, + emit log(line.replace(username, "<Username>").replace(sessionID, "<Session ID>"), getLevel(line, MessageLevel::Message)); } if (!complete) @@ -111,19 +111,24 @@ void MinecraftProcess::on_stdOut() // exit handler void MinecraftProcess::finish(int code, ExitStatus status) { - if (status != NormalExit) + if (!killed) { - // TODO: error handling + if (status == NormalExit) + { + //: Message displayed on instance exit + emit log(tr("Minecraft exited with exitcode %1.").arg(code)); + } + else + { + //: Message displayed on instance crashed + emit log(tr("Minecraft crashed with exitcode %1.").arg(code)); + } } - - // TODO: Localization - - if (!killed) - //: Message displayed on instance exit - emit log(tr("Minecraft exited with exitcode %1.").arg(status)); else + { //: Message displayed after the instance exits due to kill request emit log(tr("Minecraft was killed by user."), MessageLevel::Error); + } m_prepostlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(code)); @@ -134,11 +139,12 @@ void MinecraftProcess::finish(int code, ExitStatus status) m_prepostlaunchprocess.waitForFinished(); if (m_prepostlaunchprocess.exitStatus() != NormalExit) { - // TODO: error handling + emit postlaunch_failed(m_instance, m_prepostlaunchprocess.exitCode(), + m_prepostlaunchprocess.exitStatus()); } } m_instance->cleanupAfterRun(); - emit ended(m_instance); + emit ended(m_instance, code, status); } void MinecraftProcess::killMinecraft() @@ -155,7 +161,9 @@ void MinecraftProcess::launch() m_prepostlaunchprocess.waitForFinished(); if (m_prepostlaunchprocess.exitStatus() != NormalExit) { - // TODO: error handling + m_instance->cleanupAfterRun(); + emit prelaunch_failed(m_instance, m_prepostlaunchprocess.exitCode(), + m_prepostlaunchprocess.exitStatus()); return; } } @@ -166,15 +174,15 @@ void MinecraftProcess::launch() QString JavaPath = m_instance->settings().get("JavaPath").toString(); emit log(QString("Java path: '%1'").arg(JavaPath)); emit log(QString("Arguments: '%1'").arg( - m_args.join("' '") /*.replace(username, "<Username>").replace(sessionID, "<Session -ID>")*/)); + m_args.join("' '").replace(username, "<Username>").replace(sessionID, "<Session ID>"))); start(JavaPath, m_args); if (!waitForStarted()) { //: Error message displayed if instace can't start - emit log(tr("Could not launch minecraft!")); + emit log(tr("Could not launch minecraft!"), MessageLevel::Error); + m_instance->cleanupAfterRun(); + emit launch_failed(m_instance); return; - // TODO: error handling } } diff --git a/logic/MinecraftProcess.h b/logic/MinecraftProcess.h index ad887c5b..e38d2f83 100644 --- a/logic/MinecraftProcess.h +++ b/logic/MinecraftProcess.h @@ -58,9 +58,14 @@ public: */ void launch(); - void setMinecraftWorkdir(QString path); + BaseInstance *instance() + { + return m_instance; + } + + void setWorkdir(QString path); - void setMinecraftArguments(QStringList args); + void setArguments(QStringList args); void killMinecraft(); @@ -72,9 +77,24 @@ public: signals: /** + * @brief emitted when Minecraft immediately fails to run + */ + void launch_failed(BaseInstance *); + + /** + * @brief emitted when the PreLaunchCommand fails + */ + void prelaunch_failed(BaseInstance *, int code, QProcess::ExitStatus status); + + /** + * @brief emitted when the PostLaunchCommand fails + */ + void postlaunch_failed(BaseInstance *, int code, QProcess::ExitStatus status); + + /** * @brief emitted when mc has finished and the PostLaunchCommand was run */ - void ended(BaseInstance *); + void ended(BaseInstance *, int code, QProcess::ExitStatus status); /** * @brief emitted when we want to log something diff --git a/logic/OneSixAssets.cpp b/logic/OneSixAssets.cpp index dbc42262..400aff2c 100644 --- a/logic/OneSixAssets.cpp +++ b/logic/OneSixAssets.cpp @@ -22,6 +22,8 @@ #include "net/S3ListBucket.h" #include "MultiMC.h" +#define ASSETS_URL "http://resources.download.minecraft.net/" + class ThreadedDeleter : public QThread { Q_OBJECT @@ -69,7 +71,7 @@ void OneSixAssets::downloadFinished() void OneSixAssets::S3BucketFinished() { - QString prefix("http://s3.amazonaws.com/Minecraft.Resources/"); + QString prefix(ASSETS_URL); nuke_whitelist.clear(); emit filesStarted(); @@ -114,7 +116,7 @@ void OneSixAssets::S3BucketFinished() void OneSixAssets::start() { auto job = new NetJob("Assets index"); - job->addNetAction(S3ListBucket::make(QUrl("http://s3.amazonaws.com/Minecraft.Resources/"))); + job->addNetAction(S3ListBucket::make(QUrl(ASSETS_URL))); connect(job, SIGNAL(succeeded()), SLOT(S3BucketFinished())); connect(job, SIGNAL(failed()), SIGNAL(failed())); emit indexStarted(); diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index 5a83bafc..a947b7c0 100644 --- a/logic/OneSixInstance.cpp +++ b/logic/OneSixInstance.cpp @@ -18,6 +18,7 @@ #include "OneSixUpdate.h" #include "MinecraftProcess.h" #include "OneSixVersion.h" +#include "JavaChecker.h" #include <setting.h> #include <pathutils.h> @@ -36,7 +37,7 @@ OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *setting_o reloadFullVersion(); } -BaseUpdate *OneSixInstance::doUpdate() +Task *OneSixInstance::doUpdate() { return new OneSixUpdate(this); } @@ -74,7 +75,7 @@ QStringList OneSixInstance::processMinecraftArgs(MojangAccountPtr account) QMap<QString, QString> token_mapping; // yggdrasil! token_mapping["auth_username"] = account->username(); - //token_mapping["auth_session"] = response.session_id; + token_mapping["auth_session"] = account->sessionId(); token_mapping["auth_access_token"] = account->accessToken(); token_mapping["auth_player_name"] = account->currentProfile()->name(); token_mapping["auth_uuid"] = account->currentProfile()->id(); @@ -93,6 +94,8 @@ QStringList OneSixInstance::processMinecraftArgs(MojangAccountPtr account) token_mapping["game_directory"] = absRootDir; QString absAssetsDir = QDir("assets/").absolutePath(); token_mapping["game_assets"] = absAssetsDir; + //TODO: this is something new and not even fully implemented in the vanilla launcher. + token_mapping["user_properties"] = "{ }"; QStringList parts = args_pattern.split(' ', QString::SkipEmptyParts); for (int i = 0; i < parts.length(); i++) @@ -120,6 +123,11 @@ MinecraftProcess *OneSixInstance::prepareForLaunch(MojangAccountPtr account) for (auto lib : libs_to_extract) { + QString storage = lib->storagePath(); + if(storage.contains("${arch}")) + { + storage.replace("${arch}", "64"); + } QString path = "libraries/" + lib->storagePath(); QLOG_INFO() << "Will extract " << path.toLocal8Bit(); if (JlCompress::extractWithExceptions(path, natives_dir_raw, lib->extract_excludes) @@ -186,8 +194,8 @@ MinecraftProcess *OneSixInstance::prepareForLaunch(MojangAccountPtr account) // create the process and set its parameters MinecraftProcess *proc = new MinecraftProcess(this); - proc->setMinecraftArguments(args); - proc->setMinecraftWorkdir(minecraftRoot()); + proc->setArguments(args); + proc->setWorkdir(minecraftRoot()); return proc; } diff --git a/logic/OneSixInstance.h b/logic/OneSixInstance.h index c1c742a8..e30ca7ca 100644 --- a/logic/OneSixInstance.h +++ b/logic/OneSixInstance.h @@ -20,7 +20,7 @@ #include "BaseInstance.h" class OneSixVersion; -class BaseUpdate; +class Task; class ModList; class OneSixInstance : public BaseInstance @@ -39,8 +39,9 @@ public: QString loaderModsDir() const; virtual QString instanceConfigFolder() const; - virtual BaseUpdate *doUpdate(); + virtual Task *doUpdate(); virtual MinecraftProcess *prepareForLaunch(MojangAccountPtr account); + virtual void cleanupAfterRun(); virtual QString intendedVersionId() const; diff --git a/logic/OneSixRule.h b/logic/OneSixRule.h index 9cd1a226..5a13cbd9 100644 --- a/logic/OneSixRule.h +++ b/logic/OneSixRule.h @@ -16,7 +16,6 @@ #pragma once #include <QString> -#include <QSharedPointer> #include "logic/OneSixLibrary.h" diff --git a/logic/OneSixUpdate.cpp b/logic/OneSixUpdate.cpp index 2d8a167c..c69ff155 100644 --- a/logic/OneSixUpdate.cpp +++ b/logic/OneSixUpdate.cpp @@ -28,10 +28,11 @@ #include "OneSixVersion.h" #include "OneSixLibrary.h" #include "OneSixInstance.h" +#include "net/ForgeMirrors.h" #include "pathutils.h" -OneSixUpdate::OneSixUpdate(BaseInstance *inst, QObject *parent) : BaseUpdate(inst, parent) +OneSixUpdate::OneSixUpdate(BaseInstance *inst, QObject *parent) : Task(parent), m_inst(inst) { } @@ -142,7 +143,7 @@ void OneSixUpdate::jarlibStart() bool successful = inst->reloadFullVersion(); if (!successful) { - emitFailed("Failed to load the version description file (version.json). It might be " + emitFailed("Failed to load the version description file. It might be " "corrupted, missing or simply too new."); return; } @@ -163,20 +164,53 @@ void OneSixUpdate::jarlibStart() libs.append(version->getActiveNormalLibs()); auto metacache = MMC->metacache(); + QList<ForgeXzDownloadPtr> ForgeLibs; + bool already_forge_xz = false; for (auto lib : libs) { if (lib->hint() == "local") continue; - QString download_path = lib->downloadUrl(); - auto entry = metacache->resolveEntry("libraries", lib->storagePath()); + QString storage = lib->storagePath(); + QString dl = lib->downloadUrl(); + if (lib->isNative() && storage.contains("${arch}")) + { + auto storage64 = storage, storage32 = storage; + auto dl64 = dl, dl32 = dl; + storage64.replace("${arch}", "64"); + storage32.replace("${arch}", "32"); + dl32.replace("${arch}", "32"); + dl64.replace("${arch}", "64"); + + auto entry64 = metacache->resolveEntry("libraries", storage64); + if (entry64->stale) + jarlibDownloadJob->addNetAction(CacheDownload::make(dl64, entry64)); + + auto entry32 = metacache->resolveEntry("libraries", storage32); + if (entry32->stale) + jarlibDownloadJob->addNetAction(CacheDownload::make(dl32, entry32)); + continue; + } + auto entry = metacache->resolveEntry("libraries", storage); if (entry->stale) { if (lib->hint() == "forge-pack-xz") - jarlibDownloadJob->addNetAction(ForgeXzDownload::make(download_path, entry)); + { + ForgeLibs.append(ForgeXzDownload::make(storage, entry)); + } else - jarlibDownloadJob->addNetAction(CacheDownload::make(download_path, entry)); + { + jarlibDownloadJob->addNetAction(CacheDownload::make(dl, entry)); + } } } + // TODO: think about how to propagate this from the original json file... or IF AT ALL + QString forgeMirrorList = "http://files.minecraftforge.net/mirror-brand.list"; + if (!ForgeLibs.empty()) + { + jarlibDownloadJob->addNetAction( + ForgeMirrors::make(ForgeLibs, jarlibDownloadJob, forgeMirrorList)); + } + connect(jarlibDownloadJob.get(), SIGNAL(succeeded()), SLOT(jarlibFinished())); connect(jarlibDownloadJob.get(), SIGNAL(failed()), SLOT(jarlibFailed())); connect(jarlibDownloadJob.get(), SIGNAL(progress(qint64, qint64)), diff --git a/logic/OneSixUpdate.h b/logic/OneSixUpdate.h index e5f553c7..a66da067 100644 --- a/logic/OneSixUpdate.h +++ b/logic/OneSixUpdate.h @@ -21,12 +21,11 @@ #include "logic/net/NetJob.h" #include "logic/tasks/Task.h" -#include "logic/BaseUpdate.h" class MinecraftVersion; class BaseInstance; -class OneSixUpdate : public BaseUpdate +class OneSixUpdate : public Task { Q_OBJECT public: @@ -49,4 +48,5 @@ private: // target version, determined during this task std::shared_ptr<MinecraftVersion> targetVersion; + BaseInstance *m_inst; }; diff --git a/logic/OneSixVersion.cpp b/logic/OneSixVersion.cpp index 01bf41f4..4e2bbda5 100644 --- a/logic/OneSixVersion.cpp +++ b/logic/OneSixVersion.cpp @@ -151,7 +151,7 @@ std::shared_ptr<OneSixVersion> OneSixVersion::fromJson(QJsonObject root) root.value("minimumLauncherVersion").toDouble(); // ADD MORE HERE :D - if (launcher_ver > 0 && launcher_ver <= 9) + if (launcher_ver > 0 && launcher_ver <= 10) return fromJsonV4(root, readVersion); else { diff --git a/logic/auth/MojangAccount.cpp b/logic/auth/MojangAccount.cpp index 4875e5f7..4f3839bc 100644 --- a/logic/auth/MojangAccount.cpp +++ b/logic/auth/MojangAccount.cpp @@ -82,6 +82,10 @@ void MojangAccount::setAccessToken(const QString& accessToken) m_accessToken = accessToken; } +QString MojangAccount::sessionId() const +{ + return "token:" + m_accessToken + ":" + currentProfile()->id(); +} const QList<AccountProfile> MojangAccount::profiles() const { diff --git a/logic/auth/MojangAccount.h b/logic/auth/MojangAccount.h index e5684b77..062b8aa2 100644 --- a/logic/auth/MojangAccount.h +++ b/logic/auth/MojangAccount.h @@ -110,13 +110,18 @@ public: * If the user has not chosen to stay logged in, this will be an empty string. */ QString accessToken() const; - + /** * Changes this MojangAccount's access token to the given value. */ void setAccessToken(const QString& token); /** + * Get full session ID + */ + QString sessionId() const; + + /** * Returns a list of the available account profiles. */ const ProfileList profiles() const; diff --git a/logic/lists/BaseVersionList.h b/logic/lists/BaseVersionList.h index 5ac9369b..21b44e8d 100644 --- a/logic/lists/BaseVersionList.h +++ b/logic/lists/BaseVersionList.h @@ -18,7 +18,6 @@ #include <QObject> #include <QVariant> #include <QAbstractListModel> -#include <QSharedPointer> #include "logic/BaseVersion.h" diff --git a/logic/lists/ForgeVersionList.h b/logic/lists/ForgeVersionList.h index 0d10e1f3..bf9e87b2 100644 --- a/logic/lists/ForgeVersionList.h +++ b/logic/lists/ForgeVersionList.h @@ -17,7 +17,6 @@ #include <QObject> #include <QAbstractListModel> -#include <QSharedPointer> #include <QUrl> #include <QNetworkReply> diff --git a/logic/lists/InstanceList.h b/logic/lists/InstanceList.h index c3e3561d..d08501eb 100644 --- a/logic/lists/InstanceList.h +++ b/logic/lists/InstanceList.h @@ -16,7 +16,6 @@ #pragma once #include <QObject> -#include <QSharedPointer> #include <QAbstractListModel> #include "categorizedsortfilterproxymodel.h" #include <QIcon> diff --git a/logic/lists/JavaVersionList.h b/logic/lists/JavaVersionList.h index 4826ca0c..f816c932 100644 --- a/logic/lists/JavaVersionList.h +++ b/logic/lists/JavaVersionList.h @@ -17,7 +17,6 @@ #include <QObject> #include <QAbstractListModel> -#include <QSharedPointer> #include "BaseVersionList.h" #include "logic/tasks/Task.h" diff --git a/logic/lists/MinecraftVersionList.h b/logic/lists/MinecraftVersionList.h index 90b1ae86..82af1009 100644 --- a/logic/lists/MinecraftVersionList.h +++ b/logic/lists/MinecraftVersionList.h @@ -18,7 +18,6 @@ #include <QObject> #include <QList> #include <QSet> -#include <QSharedPointer> #include "BaseVersionList.h" #include "logic/tasks/Task.h" diff --git a/logic/net/CacheDownload.cpp b/logic/net/CacheDownload.cpp index 4fe4e68e..873d3a2e 100644 --- a/logic/net/CacheDownload.cpp +++ b/logic/net/CacheDownload.cpp @@ -29,7 +29,6 @@ CacheDownload::CacheDownload(QUrl url, MetaEntryPtr entry) m_entry = entry; m_target_path = entry->getFullPath(); m_status = Job_NotStarted; - m_opened_for_saving = false; } void CacheDownload::start() @@ -87,7 +86,7 @@ void CacheDownload::downloadFinished() // nothing went wrong... m_status = Job_Finished; - if (m_opened_for_saving) + if (m_output_file.isOpen()) { // save the data to the downloadable if we aren't saving to file m_output_file.close(); @@ -133,7 +132,7 @@ void CacheDownload::downloadFinished() void CacheDownload::downloadReadyRead() { - if (!m_opened_for_saving) + if (!m_output_file.isOpen()) { if (!m_output_file.open(QIODevice::WriteOnly)) { @@ -144,7 +143,6 @@ void CacheDownload::downloadReadyRead() emit failed(index_within_job); return; } - m_opened_for_saving = true; } QByteArray ba = m_reply->readAll(); md5sum.addData(ba); diff --git a/logic/net/CacheDownload.h b/logic/net/CacheDownload.h index 2b9a5dd8..e25aecd2 100644 --- a/logic/net/CacheDownload.h +++ b/logic/net/CacheDownload.h @@ -26,8 +26,6 @@ class CacheDownload : public NetAction Q_OBJECT public: MetaEntryPtr m_entry; - /// is the saving file already open? - bool m_opened_for_saving; /// if saving to file, use the one specified in this string QString m_target_path; /// this is the output file, if any diff --git a/logic/net/FileDownload.cpp b/logic/net/FileDownload.cpp index 6b2aa66f..239af351 100644 --- a/logic/net/FileDownload.cpp +++ b/logic/net/FileDownload.cpp @@ -25,7 +25,6 @@ FileDownload::FileDownload(QUrl url, QString target_path) : NetAction() m_target_path = target_path; m_check_md5 = false; m_status = Job_NotStarted; - m_opened_for_saving = false; } void FileDownload::start() @@ -113,7 +112,7 @@ void FileDownload::downloadFinished() void FileDownload::downloadReadyRead() { - if (!m_opened_for_saving) + if (!m_output_file.isOpen()) { if (!m_output_file.open(QIODevice::WriteOnly)) { @@ -124,7 +123,6 @@ void FileDownload::downloadReadyRead() emit failed(index_within_job); return; } - m_opened_for_saving = true; } m_output_file.write(m_reply->readAll()); } diff --git a/logic/net/FileDownload.h b/logic/net/FileDownload.h index 31e0259c..58380e86 100644 --- a/logic/net/FileDownload.h +++ b/logic/net/FileDownload.h @@ -29,8 +29,6 @@ public: bool m_check_md5; /// the expected md5 checksum QString m_expected_md5; - /// is the saving file already open? - bool m_opened_for_saving; /// if saving to file, use the one specified in this string QString m_target_path; /// this is the output file, if any diff --git a/logic/net/ForgeMirror.h b/logic/net/ForgeMirror.h new file mode 100644 index 00000000..2518dffe --- /dev/null +++ b/logic/net/ForgeMirror.h @@ -0,0 +1,10 @@ +#pragma once +#include <QString> + +struct ForgeMirror +{ + QString name; + QString logo_url; + QString website_url; + QString mirror_url; +};
\ No newline at end of file diff --git a/logic/net/ForgeMirrors.cpp b/logic/net/ForgeMirrors.cpp new file mode 100644 index 00000000..fd7eccca --- /dev/null +++ b/logic/net/ForgeMirrors.cpp @@ -0,0 +1,116 @@ +#include "MultiMC.h" +#include "ForgeMirrors.h" +#include "logger/QsLog.h" +#include <algorithm> +#include <random> + +ForgeMirrors::ForgeMirrors(QList<ForgeXzDownloadPtr> &libs, NetJobPtr parent_job, + QString mirrorlist) +{ + m_libs = libs; + m_parent_job = parent_job; + m_url = QUrl(mirrorlist); + m_status = Job_NotStarted; +} + +void ForgeMirrors::start() +{ + QLOG_INFO() << "Downloading " << m_url.toString(); + QNetworkRequest request(m_url); + request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Uncached)"); + auto worker = MMC->qnam(); + QNetworkReply *rep = worker->get(request); + + m_reply = std::shared_ptr<QNetworkReply>(rep); + connect(rep, SIGNAL(downloadProgress(qint64, qint64)), + SLOT(downloadProgress(qint64, qint64))); + connect(rep, SIGNAL(finished()), SLOT(downloadFinished())); + connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), + SLOT(downloadError(QNetworkReply::NetworkError))); + connect(rep, SIGNAL(readyRead()), SLOT(downloadReadyRead())); +} + +void ForgeMirrors::downloadError(QNetworkReply::NetworkError error) +{ + // error happened during download. + QLOG_ERROR() << "Error getting URL:" << m_url.toString().toLocal8Bit() + << "Network error: " << error; + m_status = Job_Failed; +} + +void ForgeMirrors::downloadFinished() +{ + // if the download succeeded + if (m_status != Job_Failed) + { + // nothing went wrong... ? + parseMirrorList(); + return; + } + // else the download failed, we use a fixed list + else + { + m_status = Job_Finished; + m_reply.reset(); + deferToFixedList(); + return; + } +} + +void ForgeMirrors::deferToFixedList() +{ + m_mirrors.clear(); + m_mirrors.append( + {"Minecraft Forge", "http://files.minecraftforge.net/forge_logo.png", + "http://files.minecraftforge.net/", "http://files.minecraftforge.net/maven/"}); + m_mirrors.append({"Creeper Host", + "http://files.minecraftforge.net/forge_logo.png", + "https://www.creeperhost.net/link.php?id=1", + "http://new.creeperrepo.net/forge/maven/"}); + injectDownloads(); + emit succeeded(index_within_job); +} + +void ForgeMirrors::parseMirrorList() +{ + m_status = Job_Finished; + auto data = m_reply->readAll(); + m_reply.reset(); + auto dataLines = data.split('\n'); + for(auto line: dataLines) + { + auto elements = line.split('!'); + if (elements.size() == 4) + { + m_mirrors.append({elements[0],elements[1],elements[2],elements[3]}); + } + } + if(!m_mirrors.size()) + deferToFixedList(); + injectDownloads(); + emit succeeded(index_within_job); +} + +void ForgeMirrors::injectDownloads() +{ + // shuffle the mirrors randomly + std::random_device rd; + std::mt19937 rng(rd()); + std::shuffle(m_mirrors.begin(), m_mirrors.end(), rng); + + // tell parent to download the libs + for(auto lib: m_libs) + { + lib->setMirrors(m_mirrors); + m_parent_job->addNetAction(lib); + } +} + +void ForgeMirrors::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) +{ + emit progress(index_within_job, bytesReceived, bytesTotal); +} + +void ForgeMirrors::downloadReadyRead() +{ +} diff --git a/logic/net/ForgeMirrors.h b/logic/net/ForgeMirrors.h new file mode 100644 index 00000000..990e49d6 --- /dev/null +++ b/logic/net/ForgeMirrors.h @@ -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. + */ + +#pragma once + +#include "NetAction.h" +#include "HttpMetaCache.h" +#include "ForgeXzDownload.h" +#include "NetJob.h" +#include <QFile> +#include <QTemporaryFile> +typedef std::shared_ptr<class ForgeMirrors> ForgeMirrorsPtr; + +class ForgeMirrors : public NetAction +{ + Q_OBJECT +public: + QList<ForgeXzDownloadPtr> m_libs; + NetJobPtr m_parent_job; + QList<ForgeMirror> m_mirrors; + +public: + explicit ForgeMirrors(QList<ForgeXzDownloadPtr> &libs, NetJobPtr parent_job, + QString mirrorlist); + static ForgeMirrorsPtr make(QList<ForgeXzDownloadPtr> &libs, NetJobPtr parent_job, + QString mirrorlist) + { + return ForgeMirrorsPtr(new ForgeMirrors(libs, parent_job, mirrorlist)); + } + +protected +slots: + virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); + virtual void downloadError(QNetworkReply::NetworkError error); + virtual void downloadFinished(); + virtual void downloadReadyRead(); + +private: + void parseMirrorList(); + void deferToFixedList(); + void injectDownloads(); + +public +slots: + virtual void start(); +}; diff --git a/logic/net/ForgeXzDownload.cpp b/logic/net/ForgeXzDownload.cpp index 6c9d7a60..f119878a 100644 --- a/logic/net/ForgeXzDownload.cpp +++ b/logic/net/ForgeXzDownload.cpp @@ -22,30 +22,45 @@ #include <QDateTime> #include "logger/QsLog.h" -ForgeXzDownload::ForgeXzDownload(QUrl url, MetaEntryPtr entry) : NetAction() +ForgeXzDownload::ForgeXzDownload(QString relative_path, MetaEntryPtr entry) : NetAction() { - QString urlstr = url.toString(); - urlstr.append(".pack.xz"); - m_url = QUrl(urlstr); m_entry = entry; m_target_path = entry->getFullPath(); + m_pack200_xz_file.setFileTemplate("./dl_temp.XXXXXX"); m_status = Job_NotStarted; - m_opened_for_saving = false; + m_url_path = relative_path; +} + +void ForgeXzDownload::setMirrors(QList<ForgeMirror> &mirrors) +{ + m_mirror_index = 0; + m_mirrors = mirrors; + updateUrl(); } void ForgeXzDownload::start() { + m_status = Job_InProgress; if (!m_entry->stale) { + m_status = Job_Finished; emit succeeded(index_within_job); return; } // can we actually create the real, final file? if (!ensureFilePathExists(m_target_path)) { + m_status = Job_Failed; + emit failed(index_within_job); + return; + } + if (m_mirrors.empty()) + { + m_status = Job_Failed; emit failed(index_within_job); return; } + QLOG_INFO() << "Downloading " << m_url.toString(); QNetworkRequest request(m_url); request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->etag.toLatin1()); @@ -75,14 +90,53 @@ void ForgeXzDownload::downloadError(QNetworkReply::NetworkError error) m_status = Job_Failed; } +void ForgeXzDownload::failAndTryNextMirror() +{ + m_status = Job_Failed; + int next = m_mirror_index + 1; + if(m_mirrors.size() == next) + m_mirror_index = 0; + else + m_mirror_index = next; + + updateUrl(); + emit failed(index_within_job); +} + +void ForgeXzDownload::updateUrl() +{ + QLOG_INFO() << "Updating URL for " << m_url_path; + for (auto possible : m_mirrors) + { + QLOG_INFO() << "Possible: " << possible.name << " : " << possible.mirror_url; + } + QString aggregate = m_mirrors[m_mirror_index].mirror_url + m_url_path + ".pack.xz"; + m_url = QUrl(aggregate); +} + void ForgeXzDownload::downloadFinished() { + //TEST: defer to other possible mirrors (autofail the first one) + /* + QLOG_INFO() <<"dl " << index_within_job << " mirror " << m_mirror_index; + if( m_mirror_index == 0) + { + QLOG_INFO() <<"dl " << index_within_job << " AUTOFAIL"; + m_status = Job_Failed; + m_pack200_xz_file.close(); + m_pack200_xz_file.remove(); + m_reply.reset(); + failAndTryNextMirror(); + return; + } + */ + // if the download succeeded if (m_status != Job_Failed) { // nothing went wrong... m_status = Job_Finished; - if (m_opened_for_saving) + if (m_pack200_xz_file.isOpen()) { // we actually downloaded something! process and isntall it decompressAndInstall(); @@ -90,7 +144,8 @@ void ForgeXzDownload::downloadFinished() } else { - // something bad happened + // something bad happened -- on the local machine! + m_status = Job_Failed; m_pack200_xz_file.remove(); m_reply.reset(); emit failed(index_within_job); @@ -100,10 +155,11 @@ void ForgeXzDownload::downloadFinished() // else the download failed else { + m_status = Job_Failed; m_pack200_xz_file.close(); m_pack200_xz_file.remove(); m_reply.reset(); - emit failed(index_within_job); + failAndTryNextMirror(); return; } } @@ -111,7 +167,7 @@ void ForgeXzDownload::downloadFinished() void ForgeXzDownload::downloadReadyRead() { - if (!m_opened_for_saving) + if (!m_pack200_xz_file.isOpen()) { if (!m_pack200_xz_file.open()) { @@ -122,7 +178,6 @@ void ForgeXzDownload::downloadReadyRead() emit failed(index_within_job); return; } - m_opened_for_saving = true; } m_pack200_xz_file.write(m_reply->readAll()); } @@ -138,7 +193,7 @@ void ForgeXzDownload::decompressAndInstall() // rewind the downloaded temp file m_pack200_xz_file.seek(0); // de-xz'd file - QTemporaryFile pack200_file; + QTemporaryFile pack200_file("./dl_temp.XXXXXX"); pack200_file.open(); bool xz_success = false; @@ -155,7 +210,7 @@ void ForgeXzDownload::decompressAndInstall() if (s == nullptr) { xz_dec_end(s); - emit failed(index_within_job); + failAndTryNextMirror(); return; } b.in = in; @@ -180,7 +235,7 @@ void ForgeXzDownload::decompressAndInstall() { // msg = "Write error\n"; xz_dec_end(s); - emit failed(index_within_job); + failAndTryNextMirror(); return; } @@ -214,42 +269,43 @@ void ForgeXzDownload::decompressAndInstall() case XZ_MEM_ERROR: QLOG_ERROR() << "Memory allocation failed\n"; xz_dec_end(s); - emit failed(index_within_job); + failAndTryNextMirror(); return; case XZ_MEMLIMIT_ERROR: QLOG_ERROR() << "Memory usage limit reached\n"; xz_dec_end(s); - emit failed(index_within_job); + failAndTryNextMirror(); return; case XZ_FORMAT_ERROR: QLOG_ERROR() << "Not a .xz file\n"; xz_dec_end(s); - emit failed(index_within_job); + failAndTryNextMirror(); return; case XZ_OPTIONS_ERROR: QLOG_ERROR() << "Unsupported options in the .xz headers\n"; xz_dec_end(s); - emit failed(index_within_job); + failAndTryNextMirror(); return; case XZ_DATA_ERROR: case XZ_BUF_ERROR: QLOG_ERROR() << "File is corrupt\n"; xz_dec_end(s); - emit failed(index_within_job); + failAndTryNextMirror(); return; default: QLOG_ERROR() << "Bug!\n"; xz_dec_end(s); - emit failed(index_within_job); + failAndTryNextMirror(); return; } } } + m_pack200_xz_file.remove(); // revert pack200 pack200_file.close(); @@ -260,20 +316,22 @@ void ForgeXzDownload::decompressAndInstall() } catch (std::runtime_error &err) { + m_status = Job_Failed; QLOG_ERROR() << "Error unpacking " << pack_name.toUtf8() << " : " << err.what(); QFile f(m_target_path); if (f.exists()) f.remove(); - emit failed(index_within_job); + failAndTryNextMirror(); return; } + pack200_file.remove(); QFile jar_file(m_target_path); if (!jar_file.open(QIODevice::ReadOnly)) { jar_file.remove(); - emit failed(index_within_job); + failAndTryNextMirror(); return; } m_entry->md5sum = QCryptographicHash::hash(jar_file.readAll(), QCryptographicHash::Md5) diff --git a/logic/net/ForgeXzDownload.h b/logic/net/ForgeXzDownload.h index 9f1bb029..990f91f0 100644 --- a/logic/net/ForgeXzDownload.h +++ b/logic/net/ForgeXzDownload.h @@ -19,6 +19,8 @@ #include "HttpMetaCache.h" #include <QFile> #include <QTemporaryFile> +#include "ForgeMirror.h" + typedef std::shared_ptr<class ForgeXzDownload> ForgeXzDownloadPtr; class ForgeXzDownload : public NetAction @@ -26,19 +28,24 @@ class ForgeXzDownload : public NetAction Q_OBJECT public: MetaEntryPtr m_entry; - /// is the saving file already open? - bool m_opened_for_saving; /// if saving to file, use the one specified in this string QString m_target_path; /// this is the output file, if any QTemporaryFile m_pack200_xz_file; + /// mirror index (NOT OPTICS, I SWEAR) + int m_mirror_index = 0; + /// list of mirrors to use. Mirror has the url base + QList<ForgeMirror> m_mirrors; + /// path relative to the mirror base + QString m_url_path; public: - explicit ForgeXzDownload(QUrl url, MetaEntryPtr entry); - static ForgeXzDownloadPtr make(QUrl url, MetaEntryPtr entry) + explicit ForgeXzDownload(QString relative_path, MetaEntryPtr entry); + static ForgeXzDownloadPtr make(QString relative_path, MetaEntryPtr entry) { - return ForgeXzDownloadPtr(new ForgeXzDownload(url, entry)); + return ForgeXzDownloadPtr(new ForgeXzDownload(relative_path, entry)); } + void setMirrors(QList<ForgeMirror> & mirrors); protected slots: @@ -53,4 +60,6 @@ slots: private: void decompressAndInstall(); + void failAndTryNextMirror(); + void updateUrl(); }; diff --git a/logic/net/HttpMetaCache.h b/logic/net/HttpMetaCache.h index e91d2684..08b39fe2 100644 --- a/logic/net/HttpMetaCache.h +++ b/logic/net/HttpMetaCache.h @@ -15,7 +15,6 @@ #pragma once #include <QString> -#include <QSharedPointer> #include <QMap> #include <qtimer.h> diff --git a/logic/net/LoginTask.cpp b/logic/net/LoginTask.cpp index 4a789bb4..5607447e 100644 --- a/logic/net/LoginTask.cpp +++ b/logic/net/LoginTask.cpp @@ -27,7 +27,8 @@ #include <QJsonParseError> #include <QJsonObject> -LoginTask::LoginTask(const UserInfo &uInfo, QObject *parent) : Task(parent), uInfo(uInfo) +LoginTask::LoginTask(const PasswordLogin &loginInfo, QObject *parent) + : Task(parent), loginInfo(loginInfo) { } @@ -49,8 +50,8 @@ void LoginTask::legacyLogin() "application/x-www-form-urlencoded"); QUrlQuery params; - params.addQueryItem("user", uInfo.username); - params.addQueryItem("password", uInfo.password); + params.addQueryItem("user", loginInfo.username); + params.addQueryItem("password", loginInfo.password); params.addQueryItem("version", "13"); netReply = worker->post(netRequest, params.query(QUrl::EncodeSpaces).toUtf8()); @@ -221,8 +222,8 @@ void LoginTask::yggdrasilLogin() agent.insert("name", QString("Minecraft")); agent.insert("version", QJsonValue(1)); root.insert("agent", agent); - root.insert("username", uInfo.username); - root.insert("password", uInfo.password); + root.insert("username", loginInfo.username); + root.insert("password", loginInfo.password); root.insert("clientToken", clientToken); QJsonDocument requestDoc(root); netReply = worker->post(netRequest, requestDoc.toJson()); @@ -247,6 +248,7 @@ void LoginTask::yggdrasilLogin() void LoginTask::parseYggdrasilReply(QByteArray data) { QJsonParseError jsonError; + QLOG_DEBUG() << data; QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); if (jsonError.error != QJsonParseError::NoError) { @@ -273,6 +275,7 @@ void LoginTask::parseYggdrasilReply(QByteArray data) playerID = selectedProfileO.value("id").toString(); playerName = selectedProfileO.value("name").toString(); } + QString sessionID = "token:" + accessToken + ":" + playerID; /* struct LoginResponse @@ -285,6 +288,6 @@ void LoginTask::parseYggdrasilReply(QByteArray data) }; */ - result = {uInfo.username, sessionID, playerName, playerID, accessToken}; + result = {loginInfo.username, sessionID, playerName, playerID, accessToken}; emitSucceeded(); } diff --git a/logic/net/LoginTask.h b/logic/net/LoginTask.h index 26ac0808..fe4e6d2f 100644 --- a/logic/net/LoginTask.h +++ b/logic/net/LoginTask.h @@ -16,14 +16,20 @@ #pragma once #include "logic/tasks/Task.h" -#include <QSharedPointer> +#include <QMap> -struct UserInfo +struct PasswordLogin { QString username; QString password; }; +struct User +{ + QString id; + QMap<QString, QString> properties; +}; + struct LoginResponse { QString username; @@ -31,6 +37,7 @@ struct LoginResponse QString player_name; QString player_id; QString access_token; + User user; // FIXME: no idea what this really is yet. anything relevant? }; class QNetworkReply; @@ -39,7 +46,7 @@ class LoginTask : public Task { Q_OBJECT public: - explicit LoginTask(const UserInfo &uInfo, QObject *parent = 0); + explicit LoginTask(const PasswordLogin &loginInfo, QObject *parent = 0); LoginResponse getResult() { return result; @@ -65,5 +72,5 @@ protected: LoginResponse result; QNetworkReply *netReply; - UserInfo uInfo; + PasswordLogin loginInfo; }; diff --git a/logic/net/NetJob.cpp b/logic/net/NetJob.cpp index 21c6d3f7..333cdcbf 100644 --- a/logic/net/NetJob.cpp +++ b/logic/net/NetJob.cpp @@ -89,6 +89,7 @@ void NetJob::partProgress(int index, qint64 bytesReceived, qint64 bytesTotal) void NetJob::start() { QLOG_INFO() << m_job_name.toLocal8Bit() << " started."; + m_running = true; for (auto iter : downloads) { connect(iter.get(), SIGNAL(succeeded(int)), SLOT(partSucceeded(int))); diff --git a/logic/net/NetJob.h b/logic/net/NetJob.h index c5c0d00c..021a1550 100644 --- a/logic/net/NetJob.h +++ b/logic/net/NetJob.h @@ -40,6 +40,16 @@ public: downloads.append(action); parts_progress.append(part_info()); total_progress++; + // if this is already running, the action needs to be started right away! + if (isRunning()) + { + emit progress(current_progress, total_progress); + connect(base.get(), SIGNAL(succeeded(int)), SLOT(partSucceeded(int))); + connect(base.get(), SIGNAL(failed(int)), SLOT(partFailed(int))); + connect(base.get(), SIGNAL(progress(int, qint64, qint64)), + SLOT(partProgress(int, qint64, qint64))); + base->start(); + } return true; } diff --git a/package/linux/MultiMC b/package/linux/MultiMC index 6e77a632..a2ef0c81 100755 --- a/package/linux/MultiMC +++ b/package/linux/MultiMC @@ -1,12 +1,18 @@ -#!/bin/sh +#!/bin/bash # Basic start script for running MultiMC with the libs packaged with it. -MMC_DIR="$( cd "$( dirname "$0" )" && pwd )" +MMC_DIR=`dirname "$0"` cd "${MMC_DIR}" echo "MultiMC Dir: ${MMC_DIR}" +# Set up env export LD_LIBRARY_PATH="${MMC_DIR}/bin":$LD_LIBRARY_PATH export QT_PLUGIN_PATH="${MMC_DIR}/plugins" export QT_FONTPATH="${MMC_DIR}/fonts" -exec ${MMC_DIR}/bin/MultiMC -d ${MMC_DIR} $@ + +# Just to be sure... +chmod +x "${MMC_DIR}/bin/MultiMC" + +# run MultiMC +"${MMC_DIR}/bin/MultiMC" -d "${MMC_DIR}" $@ |