diff --git a/.gitignore b/.gitignore index 54bd5039..2ef0d673 100644 --- a/.gitignore +++ b/.gitignore @@ -1,17 +1,23 @@ Thumbs.db .kdev4 -MultiMC5.kdev4 -MultiMC.pro.user -CMakeLists.txt.user .user .directory -build resources/CMakeFiles resources/MultiMCLauncher.jar *~ *.swp html/ +# Project Files +MultiMC5.kdev4 +MultiMC.pro.user +CMakeLists.txt.user +CMakeLists.txt.user.* + +# Build dirs +build +/build-* + # Ctags File tags diff --git a/CMakeLists.txt b/CMakeLists.txt index 425ddf5f..0b276cf8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,8 @@ IF(UNIX) SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) ENDIF() +set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${PROJECT_BINARY_DIR}/jars) + ######## Set compiler flags ######## IF(APPLE) message(STATUS "Using APPLE CMAKE_CXX_FLAGS") @@ -90,8 +92,8 @@ SET(MultiMC_NEWS_RSS_URL "http://multimc.org/rss.xml" CACHE STRING "URL to fetch ######## Set version numbers ######## SET(MultiMC_VERSION_MAJOR 0) -SET(MultiMC_VERSION_MINOR 1) -SET(MultiMC_VERSION_HOTFIX 1) +SET(MultiMC_VERSION_MINOR 2) +SET(MultiMC_VERSION_HOTFIX 0) # Build number SET(MultiMC_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.") @@ -280,7 +282,6 @@ gui/dialogs/SettingsDialog.h gui/dialogs/SettingsDialog.cpp gui/dialogs/CopyInstanceDialog.h gui/dialogs/CopyInstanceDialog.cpp -gui/dialogs/dialogs/ gui/dialogs/NewInstanceDialog.cpp gui/dialogs/ProgressDialog.h gui/dialogs/ProgressDialog.cpp @@ -391,6 +392,10 @@ logic/news/NewsChecker.cpp logic/news/NewsEntry.h logic/news/NewsEntry.cpp +# Status system +logic/status/StatusChecker.h +logic/status/StatusChecker.cpp + # legacy instances logic/LegacyInstance.h logic/LegacyInstance.cpp @@ -514,10 +519,16 @@ gui/widgets/MCModInfoFrame.ui set (FILES_TO_TRANSLATE ${FILES_TO_TRANSLATE} ${MULTIMC_SOURCES} ${MULTIMC_UIS}) +SET(MULTIMC_QRCS +resources/backgrounds/backgrounds.qrc +resources/multimc/multimc.qrc +resources/instances/instances.qrc +) + ######## Windows resource files ######## IF(WIN32) -SET(MULTIMC_RCS multimc.rc) +SET(MULTIMC_RCS resources/multimc.rc) ENDIF() ####### X11 Stuff ####### @@ -532,13 +543,6 @@ ENDIF() ################################ COMPILE ################################ -# ICNS file for OS X -IF(APPLE) - SET(MACOSX_BUNDLE_ICON_FILE MultiMC.icns) - SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/MultiMC.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources) - SET(MULTIMC_SOURCES ${MULTIMC_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/MultiMC.icns) -ENDIF(APPLE) - # Link additional libraries IF(WIN32) SET(MultiMC_LINK_ADDITIONAL_LIBS ${MultiMC_LINK_ADDITIONAL_LIBS} @@ -564,12 +568,10 @@ ENDIF(MultiMC_CODE_COVERAGE) # Qt 5 stuff QT5_WRAP_UI(MULTIMC_UI ${MULTIMC_UIS}) -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) +QT5_ADD_RESOURCES(MULTIMC_RESOURCES ${MULTIMC_QRCS}) # Add common library -ADD_LIBRARY(MultiMC_common STATIC ${MULTIMC_SOURCES} ${MULTIMC_UI} ${GENERATED_QRC} ${GRAPHICS_QRC}) +ADD_LIBRARY(MultiMC_common STATIC ${MULTIMC_SOURCES} ${MULTIMC_UI} ${MULTIMC_RESOURCES}) # Add executable ADD_EXECUTABLE(MultiMC MACOSX_BUNDLE WIN32 main.cpp ${MULTIMC_RCS}) @@ -579,7 +581,6 @@ TARGET_LINK_LIBRARIES(MultiMC MultiMC_common) TARGET_LINK_LIBRARIES(MultiMC_common xz-embedded unpack200 quazip libUtil libSettings libGroupView ${MultiMC_LINK_ADDITIONAL_LIBS}) QT5_USE_MODULES(MultiMC Core Widgets Network Xml Concurrent ${MultiMC_QT_ADDITIONAL_MODULES}) QT5_USE_MODULES(MultiMC_common Core Widgets Network Xml Concurrent ${MultiMC_QT_ADDITIONAL_MODULES}) -ADD_DEPENDENCIES(MultiMC_common MultiMCLauncher JavaCheck) ################################ INSTALLATION AND PACKAGING ################################ @@ -667,6 +668,11 @@ FILE(WRITE \"\${CMAKE_INSTALL_PREFIX}/${QTCONF_DEST_DIR}/qt.conf\" \"\") COMPONENT Runtime ) +# ICNS file for OS X +IF(APPLE) + INSTALL(FILES resources/MultiMC.icns DESTINATION MultiMC.app/Contents/Resources) +ENDIF() + CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/install_prereqs.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/install_prereqs.cmake" diff --git a/MultiMC.cpp b/MultiMC.cpp index 17fc2e0a..e4a30f22 100644 --- a/MultiMC.cpp +++ b/MultiMC.cpp @@ -20,8 +20,11 @@ #include "logic/news/NewsChecker.h" +#include "logic/status/StatusChecker.h" + #include "logic/InstanceLauncher.h" #include "logic/net/HttpMetaCache.h" +#include "logic/net/URLConstants.h" #include "logic/JavaUtils.h" @@ -44,8 +47,6 @@ MultiMC::MultiMC(int &argc, char **argv, bool root_override) setOrganizationName("MultiMC"); setApplicationName("MultiMC5"); - initTranslations(); - setAttribute(Qt::AA_UseHighDpiPixmaps); // Don't quit on hiding the last window this->setQuitOnLastWindowClosed(false); @@ -172,6 +173,9 @@ MultiMC::MultiMC(int &argc, char **argv, bool root_override) // load settings initGlobalSettings(); + // load translations + initTranslations(); + // initialize the updater m_updateChecker.reset(new UpdateChecker()); @@ -181,6 +185,9 @@ MultiMC::MultiMC(int &argc, char **argv, bool root_override) // initialize the news checker m_newsChecker.reset(new NewsChecker(NEWS_RSS_URL)); + // initialize the status checker + m_statusChecker.reset(new StatusChecker()); + // and instances auto InstDirSetting = m_settings->getSetting("InstanceDir"); m_instances.reset(new InstanceList(InstDirSetting->get().toString(), this)); @@ -234,18 +241,20 @@ MultiMC::~MultiMC() void MultiMC::initTranslations() { + QLocale locale(m_settings->get("Language").toString()); + QLocale::setDefault(locale); + QLOG_INFO() << "Your language is" << locale.bcp47Name(); m_qt_translator.reset(new QTranslator()); - if (m_qt_translator->load("qt_" + QLocale::system().name(), + if (m_qt_translator->load("qt_" + locale.bcp47Name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { - std::cout << "Loading Qt Language File for " - << QLocale::system().name().toLocal8Bit().constData() << "..."; + QLOG_DEBUG() << "Loading Qt Language File for" + << locale.bcp47Name().toLocal8Bit().constData() << "..."; if (!installTranslator(m_qt_translator.get())) { - std::cout << " failed."; + QLOG_ERROR() << "Loading Qt Language File failed."; m_qt_translator.reset(); } - std::cout << std::endl; } else { @@ -253,17 +262,15 @@ void MultiMC::initTranslations() } m_mmc_translator.reset(new QTranslator()); - if (m_mmc_translator->load("mmc_" + QLocale::system().name(), - QDir("translations").absolutePath())) + if (m_mmc_translator->load("mmc_" + locale.bcp47Name(), MMC->root() + "/translations")) { - std::cout << "Loading MMC Language File for " - << QLocale::system().name().toLocal8Bit().constData() << "..."; + QLOG_DEBUG() << "Loading MMC Language File for" + << locale.bcp47Name().toLocal8Bit().constData() << "..."; if (!installTranslator(m_mmc_translator.get())) { - std::cout << " failed."; + QLOG_ERROR() << "Loading MMC Language File failed."; m_mmc_translator.reset(); } - std::cout << std::endl; } else { @@ -366,9 +373,13 @@ void MultiMC::initGlobalSettings() // Editors m_settings->registerSetting("JsonEditor", QString()); + // Language + m_settings->registerSetting("Language", QLocale(QLocale::system().language()).bcp47Name()); + // Console m_settings->registerSetting("ShowConsole", true); m_settings->registerSetting("AutoCloseConsole", true); + m_settings->registerSetting("LogPrePostOutput", true); // Console Colors // m_settings->registerSetting("SysMessageColor", QColor(Qt::blue)); diff --git a/MultiMC.h b/MultiMC.h index 18c7aab7..638a442f 100644 --- a/MultiMC.h +++ b/MultiMC.h @@ -21,6 +21,7 @@ class JavaVersionList; class UpdateChecker; class NotificationChecker; class NewsChecker; +class StatusChecker; #if defined(MMC) #undef MMC @@ -113,6 +114,11 @@ public: return m_newsChecker; } + std::shared_ptr statusChecker() + { + return m_statusChecker; + } + std::shared_ptr lwjgllist(); std::shared_ptr forgelist(); @@ -183,6 +189,7 @@ private: std::shared_ptr m_updateChecker; std::shared_ptr m_notificationChecker; std::shared_ptr m_newsChecker; + std::shared_ptr m_statusChecker; std::shared_ptr m_accounts; std::shared_ptr m_icons; std::shared_ptr m_qnam; diff --git a/changelog.yaml b/changelog.yaml index 82dccd69..01e11f52 100644 --- a/changelog.yaml +++ b/changelog.yaml @@ -16,4 +16,16 @@ - Added additional information to the about dialog. 0.1.1: - Hotfix - Changed the issue tracker URL to [GitHub issues](https://github.com/MultiMC/MultiMC5/issues). - +0.2: + - Java memory settings have MB added to the number to make the units obvious. + - Complete rework of the launcher part. No more sensitive information in the process arguments. + - Cached downloads now do not destroy files on failure. + - Mojang service status is now on the MultiMC status bar. + - Java checker is no longer needed/used on instance launch. + - Support for private FTB packs. + - Fixed instance ID issues related to copying FTB packs without changing the instance name. + - Forge versions are better sorted (build numbers above 999 were sorted wrong). + - Fixed crash related to the MultiMC update channel picker in offline mode. + - Started using icon themes for the application icons, fixing many OSX graphical glitches. + - Icon sources have been located, along with icon licenses. + - Update to the German translation. diff --git a/depends/javacheck/.gitignore b/depends/javacheck/.gitignore new file mode 100644 index 00000000..cc1c52bf --- /dev/null +++ b/depends/javacheck/.gitignore @@ -0,0 +1,6 @@ +.idea +*.iml +out +.classpath +.idea +.project diff --git a/depends/launcher/.gitignore b/depends/launcher/.gitignore new file mode 100644 index 00000000..cc1c52bf --- /dev/null +++ b/depends/launcher/.gitignore @@ -0,0 +1,6 @@ +.idea +*.iml +out +.classpath +.idea +.project diff --git a/depends/launcher/CMakeLists.txt b/depends/launcher/CMakeLists.txt index 729ebb67..6af5f738 100644 --- a/depends/launcher/CMakeLists.txt +++ b/depends/launcher/CMakeLists.txt @@ -3,20 +3,33 @@ project(launcher Java) find_package(Java 1.6 REQUIRED COMPONENTS Development) include(UseJava) -set(CMAKE_JAVA_JAR_ENTRY_POINT MultiMCLauncher) +set(CMAKE_JAVA_JAR_ENTRY_POINT org.multimc.EntryPoint) set(CMAKE_JAVA_COMPILE_FLAGS -target 1.6 -source 1.6 -Xlint:deprecation -Xlint:unchecked) set(SRC - MultiMCLauncher.java + # OSX things org/simplericity/macify/eawt/Application.java org/simplericity/macify/eawt/ApplicationAdapter.java org/simplericity/macify/eawt/ApplicationEvent.java org/simplericity/macify/eawt/ApplicationListener.java org/simplericity/macify/eawt/DefaultApplication.java + + # legacy applet wrapper thing. + # The launcher has to be there for silly FML/Forge relauncher. net/minecraft/Launcher.java - MCFrame.java + org/multimc/legacy/LegacyLauncher.java + org/multimc/legacy/LegacyFrame.java + + # onesix launcher + org/multimc/onesix/OneSixLauncher.java + + # generic launcher + org/multimc/EntryPoint.java + org/multimc/Launcher.java + org/multimc/ParseException.java + org/multimc/Utils.java + org/multimc/IconLoader.java ) +add_jar(NewLaunch ${SRC}) -add_jar(MultiMCLauncher ${SRC}) - -INSTALL_JAR(MultiMCLauncher "${BINARY_DEST_DIR}/jars") +INSTALL_JAR(NewLaunch "${BINARY_DEST_DIR}/jars") diff --git a/depends/launcher/MultiMCLauncher.java b/depends/launcher/MultiMCLauncher.java deleted file mode 100644 index 09a019ce..00000000 --- a/depends/launcher/MultiMCLauncher.java +++ /dev/null @@ -1,331 +0,0 @@ -// -// Copyright 2012 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. -// - -import java.applet.Applet; -import java.awt.Dimension; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Modifier; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.zip.ZipEntry; -import java.util.zip.ZipException; -import java.util.zip.ZipFile; - -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import org.simplericity.macify.eawt.Application; -import org.simplericity.macify.eawt.DefaultApplication; - -public class MultiMCLauncher -{ - /** - * @param args - * The arguments you want to launch Minecraft with. New path, - * Username, Session ID. - */ - public static void main(String[] args) - { - if (args.length < 3) - { - System.out.println("Not enough arguments."); - System.exit(-1); - } - - // Set the OSX application icon first, if we are on OSX. - Application application = new DefaultApplication(); - if(application.isMac()) - { - try - { - BufferedImage image = ImageIO.read(new File("icon.png")); - application.setApplicationIconImage(image); - } - catch (IOException e) - { - e.printStackTrace(); - } - } - - String userName = args[0]; - String sessionId = args[1]; - String windowtitle = args[2]; - String windowParams = args[3]; - String lwjgl = args[4]; - String cwd = System.getProperty("user.dir"); - - Dimension winSize = new Dimension(854, 480); - boolean maximize = false; - boolean compatMode = false; - - - String[] dimStrings = windowParams.split("x"); - - if (windowParams.equalsIgnoreCase("compatmode")) - { - compatMode = true; - } - else if (windowParams.equalsIgnoreCase("max")) - { - maximize = true; - } - else if (dimStrings.length == 2) - { - try - { - winSize = new Dimension(Integer.parseInt(dimStrings[0]), - Integer.parseInt(dimStrings[1])); - } - catch (NumberFormatException e) - { - System.out.println("Invalid Window size argument, " + - "using default."); - } - } - else - { - System.out.println("Invalid Window size argument, " + - "using default."); - } - - try - { - File binDir = new File(cwd, "bin"); - File lwjglDir; - if(lwjgl.equalsIgnoreCase("Mojang")) - lwjglDir = binDir; - else - lwjglDir = new File(lwjgl); - - System.out.println("Loading jars..."); - String[] lwjglJars = new String[] { - "lwjgl.jar", "lwjgl_util.jar", "jinput.jar" - }; - - URL[] urls = new URL[4]; - try - { - File f = new File(binDir, "minecraft.jar"); - urls[0] = f.toURI().toURL(); - System.out.println("Loading URL: " + urls[0].toString()); - - for (int i = 1; i < urls.length; i++) - { - File jar = new File(lwjglDir, lwjglJars[i-1]); - urls[i] = jar.toURI().toURL(); - System.out.println("Loading URL: " + urls[i].toString()); - } - } - catch (MalformedURLException e) - { - System.err.println("MalformedURLException, " + e.toString()); - System.exit(5); - } - - System.out.println("Loading natives..."); - String nativesDir = new File(lwjglDir, "natives").toString(); - - System.setProperty("org.lwjgl.librarypath", nativesDir); - System.setProperty("net.java.games.input.librarypath", nativesDir); - - URLClassLoader cl = - new URLClassLoader(urls, MultiMCLauncher.class.getClassLoader()); - - // Get the Minecraft Class. - Class mc = null; - try - { - mc = cl.loadClass("net.minecraft.client.Minecraft"); - - Field f = getMCPathField(mc); - - if (f == null) - { - System.err.println("Could not find Minecraft path field. Launch failed."); - System.exit(-1); - } - - f.setAccessible(true); - f.set(null, new File(cwd)); - // And set it. - System.out.println("Fixed Minecraft Path: Field was " + f.toString()); - } - catch (ClassNotFoundException e) - { - System.err.println("Can't find main class. Searching..."); - - // Look for any class that looks like the main class. - File mcJar = new File(new File(cwd, "bin"), "minecraft.jar"); - ZipFile zip = null; - try - { - zip = new ZipFile(mcJar); - } catch (ZipException e1) - { - e1.printStackTrace(); - System.err.println("Search failed."); - System.exit(-1); - } catch (IOException e1) - { - e1.printStackTrace(); - System.err.println("Search failed."); - System.exit(-1); - } - - Enumeration entries = zip.entries(); - ArrayList classes = new ArrayList(); - - while (entries.hasMoreElements()) - { - ZipEntry entry = entries.nextElement(); - if (entry.getName().endsWith(".class")) - { - String entryName = entry.getName().substring(0, entry.getName().lastIndexOf('.')); - entryName = entryName.replace('/', '.'); - System.out.println("Found class: " + entryName); - classes.add(entryName); - } - } - - for (String clsName : classes) - { - try - { - Class cls = cl.loadClass(clsName); - if (!Runnable.class.isAssignableFrom(cls)) - { - continue; - } - else - { - System.out.println("Found class implementing runnable: " + - cls.getName()); - } - - if (getMCPathField(cls) == null) - { - continue; - } - else - { - System.out.println("Found class implementing runnable " + - "with mcpath field: " + cls.getName()); - } - - mc = cls; - break; - } - catch (ClassNotFoundException e1) - { - // Ignore - continue; - } - } - - if (mc == null) - { - System.err.println("Failed to find Minecraft main class."); - System.exit(-1); - } - else - { - System.out.println("Found main class: " + mc.getName()); - } - } - - System.setProperty("minecraft.applet.TargetDirectory", cwd); - - String[] mcArgs = new String[2]; - mcArgs[0] = userName; - mcArgs[1] = sessionId; - - if (compatMode) - { - System.out.println("Launching in compatibility mode..."); - mc.getMethod("main", String[].class).invoke(null, (Object) mcArgs); - } - else - { - System.out.println("Launching with applet wrapper..."); - try - { - Class MCAppletClass = cl.loadClass( - "net.minecraft.client.MinecraftApplet"); - Applet mcappl = (Applet) MCAppletClass.newInstance(); - MCFrame mcWindow = new MCFrame(windowtitle); - mcWindow.start(mcappl, userName, sessionId, winSize, maximize); - } catch (InstantiationException e) - { - System.out.println("Applet wrapper failed! Falling back " + - "to compatibility mode."); - mc.getMethod("main", String[].class).invoke(null, (Object) mcArgs); - } - } - } catch (ClassNotFoundException e) - { - e.printStackTrace(); - System.exit(1); - } catch (IllegalArgumentException e) - { - e.printStackTrace(); - System.exit(2); - } catch (IllegalAccessException e) - { - e.printStackTrace(); - System.exit(2); - } catch (InvocationTargetException e) - { - e.printStackTrace(); - System.exit(3); - } catch (NoSuchMethodException e) - { - e.printStackTrace(); - System.exit(3); - } catch (SecurityException e) - { - e.printStackTrace(); - System.exit(4); - } - } - - public static Field getMCPathField(Class mc) - { - Field[] fields = mc.getDeclaredFields(); - - for (int i = 0; i < fields.length; i++) - { - Field f = fields[i]; - if (f.getType() != File.class) - { - // Has to be File - continue; - } - if (f.getModifiers() != (Modifier.PRIVATE + Modifier.STATIC)) - { - // And Private Static. - continue; - } - return f; - } - return null; - } -} diff --git a/depends/launcher/net/minecraft/Launcher.java b/depends/launcher/net/minecraft/Launcher.java index 8cef35ad..c9b137e1 100644 --- a/depends/launcher/net/minecraft/Launcher.java +++ b/depends/launcher/net/minecraft/Launcher.java @@ -1,18 +1,18 @@ -// -// Copyright 2012 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. -// +/* + * Copyright 2012-2014 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. + */ package net.minecraft; @@ -38,7 +38,7 @@ public class Launcher extends Applet implements AppletStub this.setLayout(new BorderLayout()); this.add(applet, "Center"); - this.wrappedApplet = applet; + this.wrappedApplet = applet; this.documentBase = documentBase; } @@ -46,17 +46,17 @@ public class Launcher extends Applet implements AppletStub { params.put(name, value); } - + public void replace(Applet applet) { this.wrappedApplet = applet; - + applet.setStub(this); applet.setSize(getWidth(), getHeight()); - + this.setLayout(new BorderLayout()); this.add(applet, "Center"); - + applet.init(); active = true; applet.start(); @@ -99,7 +99,7 @@ public class Launcher extends Applet implements AppletStub { wrappedApplet.resize(d); } - + @Override public void init() { @@ -127,7 +127,7 @@ public class Launcher extends Applet implements AppletStub { wrappedApplet.destroy(); } - + @Override public URL getCodeBase() { return wrappedApplet.getCodeBase(); diff --git a/depends/launcher/org/multimc/EntryPoint.java b/depends/launcher/org/multimc/EntryPoint.java new file mode 100644 index 00000000..83f232f1 --- /dev/null +++ b/depends/launcher/org/multimc/EntryPoint.java @@ -0,0 +1,135 @@ +package org.multimc;/* + * Copyright 2012-2014 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. + */ + +import org.multimc.legacy.LegacyLauncher; +import org.multimc.onesix.OneSixLauncher; +import org.simplericity.macify.eawt.Application; +import org.simplericity.macify.eawt.DefaultApplication; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.*; + +public class EntryPoint +{ + private enum Action + { + Proceed, + Launch + } + + public static void main(String[] args) + { + // Set the OSX application icon first, if we are on OSX. + Application application = new DefaultApplication(); + if(application.isMac()) + { + try + { + BufferedImage image = ImageIO.read(new File("icon.png")); + application.setApplicationIconImage(image); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + EntryPoint listener = new EntryPoint(); + int retCode = listener.listen(); + if (retCode != 0) + { + System.out.println("Exiting with " + retCode); + System.exit(retCode); + } + } + + private Action parseLine(String inData) throws ParseException + { + String[] pair = inData.split(" ", 2); + if(pair.length != 2) + throw new ParseException(); + + String command = pair[0]; + String param = pair[1]; + + if(command.equals("launch")) + { + if(param.equals("legacy")) + { + m_launcher = new LegacyLauncher(); + Utils.log("Using legacy launcher."); + Utils.log(); + return Action.Launch; + } + if(param.equals("onesix")) + { + m_launcher = new OneSixLauncher(); + Utils.log("Using onesix launcher."); + Utils.log(); + return Action.Launch; + } + else + throw new ParseException(); + } + + m_params.add(command, param); + //System.out.println(command + " : " + param); + return Action.Proceed; + } + + public int listen() + { + BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in)); + boolean isListening = true; + // Main loop + while (isListening) + { + String inData=""; + try + { + // Read from the pipe one line at a time + inData = buffer.readLine(); + if (inData != null) + { + if(parseLine(inData) == Action.Launch) + { + isListening = false; + } + } + } + catch (IOException e) + { + e.printStackTrace(); + return 1; + } + catch (ParseException e) + { + e.printStackTrace(); + return 1; + } + } + if(m_launcher != null) + { + return m_launcher.launch(m_params); + } + System.err.println("No valid launcher implementation specified."); + return 1; + } + + private ParamBucket m_params = new ParamBucket(); + private org.multimc.Launcher m_launcher; +} diff --git a/depends/launcher/org/multimc/IconLoader.java b/depends/launcher/org/multimc/IconLoader.java new file mode 100644 index 00000000..f1638f3a --- /dev/null +++ b/depends/launcher/org/multimc/IconLoader.java @@ -0,0 +1,132 @@ +package org.multimc; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.nio.ByteBuffer; + +/***************************************************************************** + * A convenience class for loading icons from images. + * + * Icons loaded from this class are formatted to fit within the required + * dimension (16x16, 32x32, or 128x128). If the source image is larger than the + * target dimension, it is shrunk down to the minimum size that will fit. If it + * is smaller, then it is only scaled up if the new scale can be a per-pixel + * linear scale (i.e., x2, x3, x4, etc). In both cases, the image's width/height + * ratio is kept the same as the source image. + * + * @author Chris Molini + *****************************************************************************/ +public class IconLoader +{ + /************************************************************************* + * Loads an icon in ByteBuffer form. + * + * @param filepath + * The location of the Image to use as an icon. + * + * @return An array of ByteBuffers containing the pixel data for the icon in + * various sizes (as recommended by the OS). + *************************************************************************/ + public static ByteBuffer[] load(String filepath) + { + BufferedImage image; + try { + image = ImageIO.read ( new File( filepath ) ); + } catch ( IOException e ) { + e.printStackTrace(); + return new ByteBuffer[0]; + } + ByteBuffer[] buffers; + buffers = new ByteBuffer[1]; + buffers[0] = loadInstance(image, 128); + return buffers; + } + + /************************************************************************* + * Copies the supplied image into a square icon at the indicated size. + * + * @param image + * The image to place onto the icon. + * @param dimension + * The desired size of the icon. + * + * @return A ByteBuffer of pixel data at the indicated size. + *************************************************************************/ + private static ByteBuffer loadInstance(BufferedImage image, int dimension) + { + BufferedImage scaledIcon = new BufferedImage(dimension, dimension, + BufferedImage.TYPE_INT_ARGB_PRE); + Graphics2D g = scaledIcon.createGraphics(); + double ratio = getIconRatio(image, scaledIcon); + double width = image.getWidth() * ratio; + double height = image.getHeight() * ratio; + g.drawImage(image, (int) ((scaledIcon.getWidth() - width) / 2), + (int) ((scaledIcon.getHeight() - height) / 2), (int) (width), + (int) (height), null); + g.dispose(); + + return convertToByteBuffer(scaledIcon); + } + + /************************************************************************* + * Gets the width/height ratio of the icon. This is meant to simplify + * scaling the icon to a new dimension. + * + * @param src + * The base image that will be placed onto the icon. + * @param icon + * The icon that will have the image placed on it. + * + * @return The amount to scale the source image to fit it onto the icon + * appropriately. + *************************************************************************/ + private static double getIconRatio(BufferedImage src, BufferedImage icon) + { + double ratio = 1; + if (src.getWidth() > icon.getWidth()) + ratio = (double) (icon.getWidth()) / src.getWidth(); + else + ratio = (int) (icon.getWidth() / src.getWidth()); + if (src.getHeight() > icon.getHeight()) + { + double r2 = (double) (icon.getHeight()) / src.getHeight(); + if (r2 < ratio) + ratio = r2; + } + else + { + double r2 = (int) (icon.getHeight() / src.getHeight()); + if (r2 < ratio) + ratio = r2; + } + return ratio; + } + + /************************************************************************* + * Converts a BufferedImage into a ByteBuffer of pixel data. + * + * @param image + * The image to convert. + * + * @return A ByteBuffer that contains the pixel data of the supplied image. + *************************************************************************/ + public static ByteBuffer convertToByteBuffer(BufferedImage image) + { + byte[] buffer = new byte[image.getWidth() * image.getHeight() * 4]; + int counter = 0; + for (int i = 0; i < image.getHeight(); i++) + for (int j = 0; j < image.getWidth(); j++) + { + int colorSpace = image.getRGB(j, i); + buffer[counter + 0] = (byte) ((colorSpace << 8) >> 24); + buffer[counter + 1] = (byte) ((colorSpace << 16) >> 24); + buffer[counter + 2] = (byte) ((colorSpace << 24) >> 24); + buffer[counter + 3] = (byte) (colorSpace >> 24); + counter += 4; + } + return ByteBuffer.wrap(buffer); + } +} \ No newline at end of file diff --git a/depends/launcher/org/multimc/Launcher.java b/depends/launcher/org/multimc/Launcher.java new file mode 100644 index 00000000..1aa2b21f --- /dev/null +++ b/depends/launcher/org/multimc/Launcher.java @@ -0,0 +1,22 @@ +/* + * Copyright 2012-2014 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. + */ + +package org.multimc; + +public interface Launcher +{ + abstract int launch(ParamBucket params); +} diff --git a/depends/launcher/org/multimc/NotFoundException.java b/depends/launcher/org/multimc/NotFoundException.java new file mode 100644 index 00000000..fe154a2f --- /dev/null +++ b/depends/launcher/org/multimc/NotFoundException.java @@ -0,0 +1,21 @@ +/* + * Copyright 2012-2014 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. + */ + +package org.multimc; + +public class NotFoundException extends Exception +{ +} diff --git a/depends/launcher/org/multimc/ParamBucket.java b/depends/launcher/org/multimc/ParamBucket.java new file mode 100644 index 00000000..2e197d9f --- /dev/null +++ b/depends/launcher/org/multimc/ParamBucket.java @@ -0,0 +1,86 @@ +/* + * Copyright 2012-2014 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. + */ + +package org.multimc; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class ParamBucket +{ + public void add(String key, String value) + { + List coll = null; + if(!m_params.containsKey(key)) + { + coll = new ArrayList(); + m_params.put(key, coll); + } + else + { + coll = m_params.get(key); + } + coll.add(value); + } + + public List all(String key) throws NotFoundException + { + if(!m_params.containsKey(key)) + throw new NotFoundException(); + return m_params.get(key); + } + + public List allSafe(String key, List def) + { + if(!m_params.containsKey(key) || m_params.get(key).size() < 1) + { + return def; + } + return m_params.get(key); + } + + public List allSafe(String key) + { + return allSafe(key, new ArrayList()); + } + + public String first(String key) throws NotFoundException + { + List list = all(key); + if(list.size() < 1) + { + throw new NotFoundException(); + } + return list.get(0); + } + + public String firstSafe(String key, String def) + { + if(!m_params.containsKey(key) || m_params.get(key).size() < 1) + { + return def; + } + return m_params.get(key).get(0); + } + + public String firstSafe(String key) + { + return firstSafe(key, ""); + } + + private HashMap> m_params = new HashMap>(); +} diff --git a/depends/launcher/org/multimc/ParseException.java b/depends/launcher/org/multimc/ParseException.java new file mode 100644 index 00000000..d9e8e53e --- /dev/null +++ b/depends/launcher/org/multimc/ParseException.java @@ -0,0 +1,22 @@ +/* + * Copyright 2012-2014 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. + */ + +package org.multimc; + +public class ParseException extends java.lang.Exception +{ + +} diff --git a/depends/launcher/org/multimc/Utils.java b/depends/launcher/org/multimc/Utils.java new file mode 100644 index 00000000..df0ef861 --- /dev/null +++ b/depends/launcher/org/multimc/Utils.java @@ -0,0 +1,179 @@ +/* + * Copyright 2012-2014 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. + */ + +package org.multimc; + +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; +import java.util.List; + +public class Utils +{ + /** + * Combine two parts of a path. + * @param path1 + * @param path2 + * @return the paths, combined + */ + public static String combine (String path1, String path2) + { + File file1 = new File(path1); + File file2 = new File(file1, path2); + return file2.getPath(); + } + + /** + * Join a list of strings into a string using a separator! + * @param strings the string list to join + * @param separator the glue + * @return the result. + */ + public static String join (List strings, String separator) + { + StringBuilder sb = new StringBuilder(); + String sep = ""; + for(String s: strings) + { + sb.append(sep).append(s); + sep = separator; + } + return sb.toString(); + } + + /** + * Adds the specified library to the classpath + * + * @param s the path to add + * @throws Exception + */ + public static void addToClassPath(String s) throws Exception + { + File f = new File(s); + URL u = f.toURI().toURL(); + URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader(); + Class urlClass = URLClassLoader.class; + Method method = urlClass.getDeclaredMethod("addURL", new Class[]{URL.class}); + method.setAccessible(true); + method.invoke(urlClassLoader, new Object[]{u}); + } + + /** + * Adds many libraries to the classpath + * + * @param jars the paths to add + */ + public static boolean addToClassPath(List jars) + { + boolean pure = true; + // initialize the class path + for (String jar : jars) + { + try + { + Utils.addToClassPath(jar); + } catch (Exception e) + { + System.err.println("Unable to load: " + jar); + e.printStackTrace(System.err); + pure = false; + } + } + return pure; + } + + /** + * Adds the specified path to the java library path + * + * @param pathToAdd the path to add + * @throws Exception + */ + @Deprecated public static void addLibraryPath(String pathToAdd) throws Exception + { + final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths"); + usrPathsField.setAccessible(true); + + //get array of paths + final String[] paths = (String[]) usrPathsField.get(null); + + //check if the path to add is already present + for (String path : paths) + { + if (path.equals(pathToAdd)) + { + return; + } + } + + //add the new path + final String[] newPaths = Arrays.copyOf(paths, paths.length + 1); + newPaths[newPaths.length - 1] = pathToAdd; + usrPathsField.set(null, newPaths); + } + + /** + * Finds a field that looks like a Minecraft base folder in a supplied class + * + * @param mc the class to scan + */ + public static Field getMCPathField(Class mc) + { + Field[] fields = mc.getDeclaredFields(); + + for (Field f : fields) + { + if (f.getType() != File.class) + { + // Has to be File + continue; + } + if (f.getModifiers() != (Modifier.PRIVATE + Modifier.STATIC)) + { + // And Private Static. + continue; + } + return f; + } + return null; + } + + /** + * Log to the MultiMC console + * + * @param message A String containing the message + * @param level A String containing the level name. See MinecraftProcess::getLevel() + */ + public static void log(String message, String level) + { + // Kinda dirty + String tag = "!![" + level + "]!"; + System.out.println(tag + message.replace("\n", "\n" + tag)); + } + + public static void log(String message) + { + log(message, "MultiMC"); + } + + public static void log() + { + System.out.println(); + } +} diff --git a/depends/launcher/MCFrame.java b/depends/launcher/org/multimc/legacy/LegacyFrame.java similarity index 70% rename from depends/launcher/MCFrame.java rename to depends/launcher/org/multimc/legacy/LegacyFrame.java index ce4564c9..c3c0cafc 100644 --- a/depends/launcher/MCFrame.java +++ b/depends/launcher/org/multimc/legacy/LegacyFrame.java @@ -1,40 +1,39 @@ -// -// Copyright 2012 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. -// +package org.multimc.legacy;/* + * Copyright 2012-2014 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. + */ import net.minecraft.Launcher; + +import javax.imageio.ImageIO; import java.applet.Applet; -import java.awt.Dimension; -import java.awt.Frame; -import java.awt.Toolkit; +import java.awt.*; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; -import java.io.IOException; -import java.io.File; -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -public class MCFrame extends Frame implements WindowListener +public class LegacyFrame extends Frame implements WindowListener { private Launcher appletWrap = null; - public MCFrame ( String title ) + public LegacyFrame(String title) { super ( title ); - BufferedImage image = null; + BufferedImage image; try { image = ImageIO.read ( new File ( "icon.png" ) ); setIconImage ( image ); @@ -47,14 +46,14 @@ public class MCFrame extends Frame implements WindowListener public void start ( Applet mcApplet, String user, String session, Dimension winSize, boolean maximize ) { try { - appletWrap = new Launcher ( mcApplet, new URL ( "http://www.minecraft.net/game" ) ); + appletWrap = new Launcher( mcApplet, new URL ( "http://www.minecraft.net/game" ) ); } catch ( MalformedURLException ignored ) {} - appletWrap.setParameter ( "username", user ); appletWrap.setParameter ( "sessionid", session ); appletWrap.setParameter ( "stand-alone", "true" ); // Show the quit button. - mcApplet.setStub ( appletWrap ); - + appletWrap.setParameter ( "demo", "false" ); + appletWrap.setParameter("fullscreen", "false"); + mcApplet.setStub(appletWrap); this.add ( appletWrap ); appletWrap.setPreferredSize ( winSize ); this.pack(); @@ -63,7 +62,6 @@ public class MCFrame extends Frame implements WindowListener if ( maximize ) { this.setExtendedState ( MAXIMIZED_BOTH ); } - validate(); appletWrap.init(); appletWrap.start(); diff --git a/depends/launcher/org/multimc/legacy/LegacyLauncher.java b/depends/launcher/org/multimc/legacy/LegacyLauncher.java new file mode 100644 index 00000000..1ca37c4a --- /dev/null +++ b/depends/launcher/org/multimc/legacy/LegacyLauncher.java @@ -0,0 +1,178 @@ +package org.multimc.legacy;/* + * Copyright 2012-2014 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. + */ + +import org.multimc.Launcher; +import org.multimc.NotFoundException; +import org.multimc.ParamBucket; +import org.multimc.Utils; + +import java.applet.Applet; +import java.awt.*; +import java.io.File; +import java.lang.reflect.Field; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; + +public class LegacyLauncher implements Launcher +{ + @Override + public int launch(ParamBucket params) + { + String userName, sessionId, windowTitle, windowParams, lwjgl; + String mainClass = "net.minecraft.client.Minecraft"; + try + { + userName = params.first("userName"); + sessionId = params.first("sessionId"); + windowTitle = params.first("windowTitle"); + windowParams = params.first("windowParams"); + lwjgl = params.first("lwjgl"); + } catch (NotFoundException e) + { + System.err.println("Not enough arguments."); + return -1; + } + + String cwd = System.getProperty("user.dir"); + Dimension winSize = new Dimension(854, 480); + boolean maximize = false; + + String[] dimStrings = windowParams.split("x"); + + if (windowParams.equalsIgnoreCase("max")) + { + maximize = true; + } + else if (dimStrings.length == 2) + { + try + { + winSize = new Dimension(Integer.parseInt(dimStrings[0]), Integer.parseInt(dimStrings[1])); + } catch (NumberFormatException ignored) {} + } + + File binDir = new File(cwd, "bin"); + File lwjglDir; + if (lwjgl.equalsIgnoreCase("Mojang")) + { + lwjglDir = binDir; + } + else + { + lwjglDir = new File(lwjgl); + } + + URL[] classpath; + { + try + { + classpath = new URL[] + { + new File(binDir, "minecraft.jar").toURI().toURL(), + new File(lwjglDir, "lwjgl.jar").toURI().toURL(), + new File(lwjglDir, "lwjgl_util.jar").toURI().toURL(), + new File(lwjglDir, "jinput.jar").toURI().toURL(), + }; + } catch (MalformedURLException e) + { + System.err.println("Class path entry is badly formed:"); + e.printStackTrace(System.err); + return -1; + } + } + + String nativesDir = new File(lwjglDir, "natives").toString(); + + System.setProperty("org.lwjgl.librarypath", nativesDir); + System.setProperty("net.java.games.input.librarypath", nativesDir); + + // print the pretty things + { + Utils.log("Main Class:"); + Utils.log(" " + mainClass); + Utils.log(); + + Utils.log("Class Path:"); + for (URL s : classpath) + { + Utils.log(" " + s); + } + Utils.log(); + + Utils.log("Native Path:"); + Utils.log(" " + nativesDir); + Utils.log(); + } + + URLClassLoader cl = new URLClassLoader(classpath, LegacyLauncher.class.getClassLoader()); + + // Get the Minecraft Class and set the base folder + Class mc; + try + { + mc = cl.loadClass(mainClass); + + Field f = Utils.getMCPathField(mc); + + if (f == null) + { + System.err.println("Could not find Minecraft path field. Launch failed."); + return -1; + } + + f.setAccessible(true); + f.set(null, new File(cwd)); + } catch (Exception e) + { + System.err.println("Could not set base folder. Failed to find/access Minecraft main class:"); + e.printStackTrace(System.err); + return -1; + } + + System.setProperty("minecraft.applet.TargetDirectory", cwd); + + String[] mcArgs = new String[2]; + mcArgs[0] = userName; + mcArgs[1] = sessionId; + + Utils.log("Launching with applet wrapper..."); + try + { + Class MCAppletClass = cl.loadClass("net.minecraft.client.MinecraftApplet"); + Applet mcappl = (Applet) MCAppletClass.newInstance(); + LegacyFrame mcWindow = new LegacyFrame(windowTitle); + mcWindow.start(mcappl, userName, sessionId, winSize, maximize); + } catch (Exception e) + { + Utils.log("Applet wrapper failed:", "Error"); + e.printStackTrace(System.err); + Utils.log(); + Utils.log("Falling back to compatibility mode."); + try + { + mc.getMethod("main", String[].class).invoke(null, (Object) mcArgs); + } catch (Exception e1) + { + Utils.log("Failed to invoke the Minecraft main class:", "Fatal"); + e1.printStackTrace(System.err); + return -1; + } + } + + return 0; + } +} diff --git a/depends/launcher/org/multimc/onesix/OneSixLauncher.java b/depends/launcher/org/multimc/onesix/OneSixLauncher.java new file mode 100644 index 00000000..c1676c94 --- /dev/null +++ b/depends/launcher/org/multimc/onesix/OneSixLauncher.java @@ -0,0 +1,210 @@ +/* Copyright 2012-2014 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. + */ + +package org.multimc.onesix; + +import org.multimc.*; + +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.List; + +public class OneSixLauncher implements Launcher +{ + @Override + public int launch(ParamBucket params) + { + // get and process the launch script params + List libraries; + List mcparams; + List mods; + String mainClass; + String natives; + final String windowTitle; + String windowParams; + try + { + libraries = params.all("cp"); + mcparams = params.all("param"); + mainClass = params.first("mainClass"); + mods = params.allSafe("mods", new ArrayList()); + natives = params.first("natives"); + windowTitle = params.first("windowTitle"); + // windowParams = params.first("windowParams"); + } catch (NotFoundException e) + { + System.err.println("Not enough arguments."); + e.printStackTrace(System.err); + return -1; + } + + List allJars = new ArrayList(); + allJars.addAll(mods); + allJars.addAll(libraries); + + if(!Utils.addToClassPath(allJars)) + { + System.err.println("Halting launch due to previous errors."); + return -1; + } + + String property = System.getProperty("os.arch"); + List allNativePaths = new ArrayList(); + boolean is_64 = property.equalsIgnoreCase("x86_64") || property.equalsIgnoreCase("amd64"); + allNativePaths.add(natives); + allNativePaths.add(natives + "/" + (is_64 ? "64" : "32")); + + // print the pretty things + { + Utils.log("Main Class:"); + Utils.log(" " + mainClass); + Utils.log(); + + Utils.log("Native paths:"); + for (String s : allNativePaths) + { + Utils.log(" " + s); + } + Utils.log(); + + Utils.log("Libraries:"); + for (String s : libraries) + { + Utils.log(" " + s); + } + Utils.log(); + + if(mods.size() > 0) + { + Utils.log("Class Path Mods:"); + for (String s : mods) + { + Utils.log(" " + s); + } + Utils.log(); + } + + Utils.log("Params:"); + Utils.log(" " + mcparams.toString()); + Utils.log(); + } + + final ClassLoader cl = ClassLoader.getSystemClassLoader(); + + // set up the natives path(s). + String libpath = Utils.join(allNativePaths, String.valueOf(File.pathSeparatorChar)); + System.setProperty("java.library.path", libpath); + Field fieldSysPath; + try + { + fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths"); + fieldSysPath.setAccessible( true ); + fieldSysPath.set( null, null ); + } catch (Exception e) + { + System.err.println("Failed to set the native library path:"); + e.printStackTrace(System.err); + return -1; + } + + // Get the Minecraft Class. + Class mc; + try + { + mc = cl.loadClass(mainClass); + } catch (ClassNotFoundException e) + { + System.err.println("Failed to find Minecraft main class:"); + e.printStackTrace(System.err); + return -1; + } + + // get the main method. + Method meth; + try + { + meth = mc.getMethod("main", String[].class); + } catch (NoSuchMethodException e) + { + System.err.println("Failed to acquire the main method:"); + e.printStackTrace(System.err); + return -1; + } + + // FIXME: works only on linux, we need a better solution +/* + final java.nio.ByteBuffer[] icons = IconLoader.load("icon.png"); + new Thread() { + public void run() { + ClassLoader cl = ClassLoader.getSystemClassLoader(); + try + { + Class Display; + Method isCreated; + Method setTitle; + Method setIcon; + + Display = cl.loadClass("org.lwjgl.opengl.Display"); + isCreated = Display.getMethod("isCreated"); + setTitle = Display.getMethod("setTitle", String.class); + setIcon = Display.getMethod("setIcon", java.nio.ByteBuffer[].class); + + // set the window title? Maybe? + while(!(Boolean) isCreated.invoke(null)) + { + try + { + Thread.sleep(150); + } catch (InterruptedException ignored) {} + } + // Give it a bit more time ;) + Thread.sleep(150); + // set the title + setTitle.invoke(null,windowTitle); + // only set icon when there's actually something to set... + if(icons.length > 0) + { + setIcon.invoke(null,(Object)icons); + } + } + catch (Exception e) + { + System.err.println("Couldn't set window icon or title."); + e.printStackTrace(System.err); + } + } + } + .start(); +*/ + // start Minecraft + String[] paramsArray = mcparams.toArray(new String[mcparams.size()]); // init params accordingly + try + { + meth.invoke(null, (Object) paramsArray); // static method doesn't have an instance + } catch (Exception e) + { + System.err.println("Failed to start Minecraft:"); + e.printStackTrace(System.err); + return -1; + } + return 0; + } +} diff --git a/generated.qrc.in b/generated.qrc.in deleted file mode 100644 index 794943eb..00000000 --- a/generated.qrc.in +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/graphics.qrc b/graphics.qrc deleted file mode 100644 index 68d3beed..00000000 --- a/graphics.qrc +++ /dev/null @@ -1,51 +0,0 @@ - - - resources/icons/toolbar/about.png - resources/icons/toolbar/ReportBug.png - resources/icons/toolbar/centralmods.png - resources/icons/toolbar/checkupdate.png - resources/icons/toolbar/help.png - resources/icons/toolbar/new.png - resources/icons/toolbar/InstCopy.png - resources/icons/toolbar/NewsIcon.png - resources/icons/toolbar/refresh.png - resources/icons/toolbar/settings.png - resources/icons/toolbar/viewfolder.png - resources/icons/toolbar/Cat.png - resources/icons/toolbar/NoAccount.png - - - resources/icons/instances/brick.png - resources/icons/instances/chicken128.png - resources/icons/instances/creeper128.png - resources/icons/instances/derp.png - resources/icons/instances/diamond.png - resources/icons/instances/dirt.png - resources/icons/instances/enderman.png - resources/icons/instances/enderpearl128.png - resources/icons/instances/ftb_glow128.png - resources/icons/instances/ftb_logo128.png - resources/icons/instances/gear128.png - resources/icons/instances/gold.png - resources/icons/instances/grass.png - resources/icons/instances/herobrine128.png - resources/icons/instances/infinity128.png - resources/icons/instances/iron.png - resources/icons/instances/magitech128.png - resources/icons/instances/meat128.png - resources/icons/instances/netherstar128.png - resources/icons/instances/planks.png - resources/icons/instances/skeleton128.png - resources/icons/instances/squarecreeper128.png - resources/icons/instances/steve128.png - resources/icons/instances/stone.png - resources/icons/instances/tnt.png - - - resources/icons/multimc.svg - resources/XdgIcon.theme - - - resources/catbgrnd2.png - - diff --git a/gui/ConsoleWindow.cpp b/gui/ConsoleWindow.cpp index 84a141ce..dc36a8ff 100644 --- a/gui/ConsoleWindow.cpp +++ b/gui/ConsoleWindow.cpp @@ -140,6 +140,9 @@ void ConsoleWindow::write(QString data, MessageLevel::Enum mode) else if (mode == MessageLevel::Debug) while (iter.hasNext()) writeColor(iter.next(), "green"); + else if (mode == MessageLevel::PrePost) + while (iter.hasNext()) + writeColor(iter.next(), "grey"); // TODO: implement other MessageLevels else while (iter.hasNext()) @@ -166,6 +169,10 @@ void ConsoleWindow::on_closeButton_clicked() void ConsoleWindow::setMayClose(bool mayclose) { + if(mayclose) + ui->closeButton->setText(tr("Close")); + else + ui->closeButton->setText(tr("Hide")); m_mayclose = mayclose; } diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index 31e4b9e4..ee9c3fad 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -77,6 +77,8 @@ #include "logic/news/NewsChecker.h" +#include "logic/status/StatusChecker.h" + #include "logic/net/URLConstants.h" #include "logic/BaseInstance.h" @@ -126,7 +128,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi // Add the news label to the news toolbar. { newsLabel = new QToolButton(); - newsLabel->setIcon(QIcon(":/icons/toolbar/news")); + newsLabel->setIcon(QIcon::fromTheme("news")); newsLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); newsLabel->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); ui->newsToolBar->insertWidget(ui->actionMoreNews, newsLabel); @@ -199,7 +201,27 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi connect(MMC->instances().get(), SIGNAL(dataIsInvalid()), SLOT(selectionBad())); m_statusLeft = new QLabel(tr("No instance selected"), this); + m_statusRight = new QLabel(tr("No status available"), this); + m_statusRefresh = new QToolButton(this); + m_statusRefresh->setCheckable(true); + m_statusRefresh->setToolButtonStyle(Qt::ToolButtonIconOnly); + m_statusRefresh->setIcon(QIcon::fromTheme("refresh")); + statusBar()->addPermanentWidget(m_statusLeft, 1); + statusBar()->addPermanentWidget(m_statusRight, 0); + statusBar()->addPermanentWidget(m_statusRefresh, 0); + + // Start status checker + { + connect(MMC->statusChecker().get(), &StatusChecker::statusLoaded, this, &MainWindow::updateStatusUI); + connect(MMC->statusChecker().get(), &StatusChecker::statusLoadingFailed, this, &MainWindow::updateStatusFailedUI); + + connect(m_statusRefresh, &QAbstractButton::clicked, this, &MainWindow::reloadStatus); + connect(&statusTimer, &QTimer::timeout, this, &MainWindow::reloadStatus); + statusTimer.setSingleShot(true); + + reloadStatus(); + } // Add "manage accounts" button, right align QWidget *spacer = new QWidget(); @@ -219,8 +241,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi accountMenuButton->setMenu(accountMenu); accountMenuButton->setPopupMode(QToolButton::InstantPopup); accountMenuButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - accountMenuButton->setIcon( - QPixmap(":/icons/toolbar/noaccount").scaled(48, 48, Qt::KeepAspectRatio)); + accountMenuButton->setIcon(QIcon::fromTheme("noaccount")); QWidgetAction *accountMenuButtonAction = new QWidgetAction(this); accountMenuButtonAction->setDefaultWidget(accountMenuButton); @@ -235,17 +256,20 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi connect(MMC->accounts().get(), &MojangAccountList::listChanged, [this] { repopulateAccountsMenu(); }); - std::shared_ptr accounts = MMC->accounts(); + // Show initial account + activeAccountChanged(); + + auto accounts = MMC->accounts(); // TODO: Nicer way to iterate? for (int i = 0; i < accounts->count(); i++) { - MojangAccountPtr account = accounts->at(i); + auto account = accounts->at(i); if (account != nullptr) { auto job = new NetJob("Startup player skins: " + account->username()); - for (AccountProfile profile : account->profiles()) + for (auto profile : account->profiles()) { auto meta = MMC->metacache()->resolveEntry("skins", profile.name + ".png"); auto action = CacheDownload::make( @@ -383,7 +407,7 @@ void MainWindow::repopulateAccountsMenu() QAction *action = new QAction(tr("No Default Account"), this); action->setCheckable(true); - action->setIcon(QPixmap(":/icons/toolbar/noaccount").scaled(48, 48, Qt::KeepAspectRatio)); + action->setIcon(QIcon::fromTheme("noaccount")); action->setData(""); if (active_username.isEmpty()) { @@ -437,8 +461,7 @@ void MainWindow::activeAccountChanged() } // Set the icon to the "no account" icon. - accountMenuButton->setIcon( - QPixmap(":/icons/toolbar/noaccount").scaled(48, 48, Qt::KeepAspectRatio)); + accountMenuButton->setIcon(QIcon::fromTheme("noaccount")); } bool MainWindow::eventFilter(QObject *obj, QEvent *ev) @@ -495,6 +518,57 @@ void MainWindow::updateNewsLabel() } } +static QString convertStatus(const QString &status) +{ + QString ret = "?"; + + if(status == "green") ret = "↑"; + else if(status == "yellow") ret = "-"; + else if(status == "red") ret="↓"; + + return "" + ret + ""; +} + +void MainWindow::reloadStatus() +{ + m_statusRefresh->setChecked(true); + MMC->statusChecker()->reloadStatus(); + //updateStatusUI(); +} + +static QString makeStatusString(const QMap statuses) +{ + QString status = ""; + status += "Web: " + convertStatus(statuses["minecraft.net"]); + status += " Account: " + convertStatus(statuses["account.mojang.com"]); + status += " Skins: " + convertStatus(statuses["skins.minecraft.net"]); + status += " Auth: " + convertStatus(statuses["authserver.mojang.com"]); + status += " Session: " + convertStatus(statuses["sessionserver.mojang.com"]); + + return status; +} + +void MainWindow::updateStatusUI() +{ + auto statusChecker = MMC->statusChecker(); + auto statuses = statusChecker->getStatusEntries(); + + QString status = makeStatusString(statuses); + m_statusRefresh->setChecked(false); + + m_statusRight->setText(status); + + statusTimer.start(60 * 1000); +} + +void MainWindow::updateStatusFailedUI() +{ + m_statusRight->setText(makeStatusString(QMap())); + m_statusRefresh->setChecked(false); + + statusTimer.start(60 * 1000); +} + void MainWindow::updateAvailable(QString repo, QString versionName, int versionId) { UpdateDialog dlg; @@ -756,7 +830,7 @@ void MainWindow::on_actionChangeInstIcon_triggered() if (dlg.result() == QDialog::Accepted) { m_selectedInstance->setIconKey(dlg.selectedIconKey); - auto ico = MMC->icons()->getIcon(dlg.selectedIconKey); + auto ico = MMC->icons()->getBigIcon(dlg.selectedIconKey); ui->actionChangeInstIcon->setIcon(ico); } } @@ -765,14 +839,14 @@ void MainWindow::iconUpdated(QString icon) { if(icon == m_currentInstIcon) { - ui->actionChangeInstIcon->setIcon(MMC->icons()->getIcon(m_currentInstIcon)); + ui->actionChangeInstIcon->setIcon(MMC->icons()->getBigIcon(m_currentInstIcon)); } } void MainWindow::updateInstanceToolIcon(QString new_icon) { m_currentInstIcon = new_icon; - ui->actionChangeInstIcon->setIcon(MMC->icons()->getIcon(m_currentInstIcon)); + ui->actionChangeInstIcon->setIcon(MMC->icons()->getBigIcon(m_currentInstIcon)); } void MainWindow::setSelectedInstanceById(const QString &id) diff --git a/gui/MainWindow.h b/gui/MainWindow.h index 12d76da4..eb478776 100644 --- a/gui/MainWindow.h +++ b/gui/MainWindow.h @@ -17,6 +17,7 @@ #include #include +#include #include "logic/lists/InstanceList.h" #include "logic/BaseInstance.h" @@ -168,6 +169,12 @@ slots: void repopulateAccountsMenu(); void updateNewsLabel(); + + void updateStatusUI(); + + void updateStatusFailedUI(); + + void reloadStatus(); /*! * Runs the DownloadUpdateTask and installs updates. @@ -198,8 +205,12 @@ private: Task *m_versionLoadTask; QLabel *m_statusLeft; + QLabel *m_statusRight; + QToolButton *m_statusRefresh; QMenu *accountMenu; QToolButton *accountMenuButton; QAction *manageAccountsAction; + + QTimer statusTimer; }; diff --git a/gui/MainWindow.ui b/gui/MainWindow.ui index 16e72c2f..25af6f60 100644 --- a/gui/MainWindow.ui +++ b/gui/MainWindow.ui @@ -14,7 +14,7 @@ MultiMC 5 - + :/icons/multimc/scalable/apps/multimc.svg:/icons/multimc/scalable/apps/multimc.svg @@ -152,8 +152,7 @@ - - :/icons/toolbar/new:/icons/toolbar/new + Add Instance @@ -167,8 +166,7 @@ - - :/icons/toolbar/viewfolder:/icons/toolbar/viewfolder + View Instance Folder @@ -182,8 +180,7 @@ - - :/icons/toolbar/refresh:/icons/toolbar/refresh + Refresh @@ -197,8 +194,7 @@ - - :/icons/toolbar/centralmods:/icons/toolbar/centralmods + View Central Mods Folder @@ -212,8 +208,7 @@ - - :/icons/toolbar/checkupdate:/icons/toolbar/checkupdate + Check for Updates @@ -227,8 +222,7 @@ - - :/icons/toolbar/settings:/icons/toolbar/settings + Settings @@ -245,8 +239,7 @@ - - :/icons/toolbar/bug:/icons/toolbar/bug + Report a Bug @@ -260,8 +253,7 @@ - - :/icons/toolbar/news:/icons/toolbar/news + More News @@ -278,8 +270,7 @@ - - :/icons/toolbar/about:/icons/toolbar/about + About MultiMC @@ -332,7 +323,7 @@ true - + :/icons/instances/infinity:/icons/instances/infinity @@ -472,20 +463,18 @@ true - - :/icons/toolbar/cat:/icons/toolbar/cat + Meow - <html><head/><body><p align="center"><span style=" font-weight:600; color:#ff0004;">Catnarok!</span></p><p align="center">Or just a cat with a ball of yarn?</p><p align="center"><span style=" font-style:italic;">WHO KNOWS?!</span></p><p align="center"><img src=":/icons/instances/tnt"/></p></body></html> + <html><head/><body><p align="center">It's a fluffy kitty :3</p></body></html> - - :/icons/toolbar/copy:/icons/toolbar/copy + Copy Instance @@ -508,7 +497,9 @@ - + + + diff --git a/gui/dialogs/AboutDialog.cpp b/gui/dialogs/AboutDialog.cpp index efeea6f2..35c85815 100644 --- a/gui/dialogs/AboutDialog.cpp +++ b/gui/dialogs/AboutDialog.cpp @@ -24,6 +24,8 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDia MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); + ui->urlLabel->setOpenExternalLinks(true); + ui->icon->setPixmap(QIcon(":/icons/multimc/scalable/apps/multimc.svg").pixmap(64)); ui->title->setText("MultiMC 5 " + MMC->version().toString()); diff --git a/gui/dialogs/AboutDialog.ui b/gui/dialogs/AboutDialog.ui index b0dafb06..64a355d3 100644 --- a/gui/dialogs/AboutDialog.ui +++ b/gui/dialogs/AboutDialog.ui @@ -104,7 +104,7 @@ 0 0 689 - 331 + 311 @@ -229,7 +229,7 @@ 0 0 689 - 331 + 311 @@ -245,7 +245,7 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <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:'MS Shell Dlg 2'; font-size:10pt; 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:'MS Shell Dlg 2'; font-size:10pt;">Andrew Okin &lt;</span><a href="mailto:forkk@forkk.net"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;">forkk@forkk.net</span></a><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt;">&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-family:'MS Shell Dlg 2'; font-size:10pt;">Petr Mrázek &lt;</span><a href="mailto:peterix@gmail.com"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;">peterix@gmail.com</span></a><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt;">&gt;</span></p> @@ -282,7 +282,7 @@ p, li { white-space: pre-wrap; } 0 0 689 - 331 + 311 @@ -309,7 +309,7 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'DejaVu Sans Mono'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'DejaVu Sans Mono'; 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-family:'Bitstream Vera Sans'; 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-size:10pt;">Copyright 2012-2014 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-size:10pt;">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></p> @@ -430,7 +430,36 @@ 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-size:8pt;"> *</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:8pt;"> * 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:8pt;"> * 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:8pt;"> */</span></p></body></html> +<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:8pt;"> */</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:8pt;"><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-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">Java IconLoader class</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=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Copyright (c) 2011, Chris Molini</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:8pt;">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:8pt;"><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:8pt;">Redistribution and use in source and binary forms, with or without</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:8pt;">modification, are permitted provided that the following conditions are met:</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:8pt;"> * Redistributions of source code must retain the above copyright</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:8pt;"> notice, this 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:8pt;"> * Redistributions in binary form must reproduce the above copyright</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:8pt;"> notice, this list of conditions and the following disclaimer in the</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:8pt;"> documentation and/or other 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:8pt;"> * Neither the name of the &lt;organization&gt; nor the</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:8pt;"> names of its contributors may 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:8pt;"> 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:8pt;"><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:8pt;">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:8pt;">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:8pt;">WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 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:8pt;">DISCLAIMED. IN NO EVENT SHALL &lt;COPYRIGHT HOLDER&gt; BE LIABLE FOR ANY</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:8pt;">DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES</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:8pt;">(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;</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:8pt;">LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 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:8pt;">ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT</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:8pt;">(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 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:8pt;">SOFTWARE, EVEN IF ADVISED 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:8pt;"><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:8pt;"><br /></p></body></html> @@ -442,7 +471,7 @@ p, li { white-space: pre-wrap; } 0 0 689 - 331 + 311 @@ -455,12 +484,12 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> -<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:'Bitstream Vera Sans'; font-size:11pt;">We keep MultiMC open source because we think it's important to be able to see the source code for a project like this, and we do so using the Apache 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:'Bitstream Vera Sans'; font-size:11pt;"><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:'Bitstream Vera Sans'; font-size:11pt;">Part of the reason for using the Apache license is we don't want people using the &quot;MultiMC&quot; name when redistributing the project. This means people must take the time to go through the source code and remove all references to &quot;MultiMC&quot;, including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).</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:'Bitstream Vera Sans'; font-size:11pt;"><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:'Bitstream Vera Sans'; font-size:11pt;">The Apache license covers reasonable use for the name - a mention of the project's origins in the About dialog and the license is acceptable. However, it should be abundantly clear that the project is a fork </span><span style=" font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:600;">without</span><span style=" font-family:'Bitstream Vera Sans'; font-size:11pt;"> implying that you have our blessing.</span></p></body></html> +</style></head><body style=" font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">We keep MultiMC open source because we think it's important to be able to see the source code for a project like this, and we do so using the Apache license.</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=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Part of the reason for using the Apache license is we don't want people using the &quot;MultiMC&quot; name when redistributing the project. This means people must take the time to go through the source code and remove all references to &quot;MultiMC&quot;, including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).</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=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Apache license covers reasonable use for the name - a mention of the project's origins in the About dialog and the license is acceptable. However, it should be abundantly clear that the project is a fork <span style=" font-weight:600;">without</span> implying that you have our blessing.</p></body></html> Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse diff --git a/gui/dialogs/InstanceSettings.ui b/gui/dialogs/InstanceSettings.ui index 9260caea..9c7e1757 100644 --- a/gui/dialogs/InstanceSettings.ui +++ b/gui/dialogs/InstanceSettings.ui @@ -168,6 +168,12 @@ + + The maximum amount of memory Minecraft is allowed to use. + + + MB + 512 @@ -198,6 +204,12 @@ + + The amount of memory Minecraft is started with. + + + MB + 256 @@ -214,6 +226,12 @@ + + The amount of memory available to store loaded Java classes. + + + MB + 64 diff --git a/gui/dialogs/ModEditDialogCommon.cpp b/gui/dialogs/ModEditDialogCommon.cpp index 9a15d92d..eee42e5e 100644 --- a/gui/dialogs/ModEditDialogCommon.cpp +++ b/gui/dialogs/ModEditDialogCommon.cpp @@ -50,8 +50,8 @@ void showWebsiteForMod(QWidget *parentDlg, Mod &m) else { CustomMessageBox::selectable( - parentDlg, parentDlg->tr("How sad!"), - parentDlg->tr("The mod author didn't provide a website link for this mod."), + parentDlg, QObject::tr("How sad!"), + QObject::tr("The mod author didn't provide a website link for this mod."), QMessageBox::Warning); } } diff --git a/gui/dialogs/SettingsDialog.cpp b/gui/dialogs/SettingsDialog.cpp index 00b3b1fd..ef363f02 100644 --- a/gui/dialogs/SettingsDialog.cpp +++ b/gui/dialogs/SettingsDialog.cpp @@ -269,6 +269,10 @@ void SettingsDialog::refreshUpdateChannelDesc() // Get the channel list. QList channelList = MMC->updateChecker()->getChannelList(); int selectedIndex = ui->updateChannelComboBox->currentIndex(); + if(selectedIndex < 0) + { + return; + } if (selectedIndex < channelList.count()) { // Find the channel list entry with the given index. @@ -284,6 +288,9 @@ void SettingsDialog::refreshUpdateChannelDesc() void SettingsDialog::applySettings(SettingsObject *s) { + // Language + s->set("Language", ui->languageBox->itemData(ui->languageBox->currentIndex()).toLocale().bcp47Name()); + // Updates s->set("AutoUpdate", ui->autoUpdateCheckBox->isChecked()); s->set("UpdateChannel", m_currentUpdateChannel); @@ -365,6 +372,19 @@ void SettingsDialog::applySettings(SettingsObject *s) void SettingsDialog::loadSettings(SettingsObject *s) { + // Language + ui->languageBox->clear(); + ui->languageBox->addItem(tr("English"), QLocale(QLocale::English)); + foreach(const QString & lang, + QDir(MMC->root() + "/translations").entryList(QStringList() << "*.qm", QDir::Files)) + { + QLocale locale(lang.section(QRegExp("[_\.]"), 1)); + ui->languageBox->addItem( + QLocale::languageToString(locale.language()), + locale); + } + ui->languageBox->setCurrentIndex(ui->languageBox->findData(QLocale(s->get("Language").toString()))); + // Updates ui->autoUpdateCheckBox->setChecked(s->get("AutoUpdate").toBool()); m_currentUpdateChannel = s->get("UpdateChannel").toString(); diff --git a/gui/dialogs/SettingsDialog.ui b/gui/dialogs/SettingsDialog.ui index 251e7916..54e7db7a 100644 --- a/gui/dialogs/SettingsDialog.ui +++ b/gui/dialogs/SettingsDialog.ui @@ -6,8 +6,8 @@ 0 0 - 526 - 723 + 545 + 609 @@ -35,43 +35,11 @@ 0 - + - General + Features - - - - - true - - - Sorting Mode - - - - - - By last launched - - - sortingModeGroup - - - - - - - By name - - - sortingModeGroup - - - - - - + @@ -86,32 +54,28 @@ - - - - - Update Channel: - - - - - - - false - - - - - - - No channel selected. - - - true - - - - + + + Update Channel: + + + + + + + false + + + + + + + No channel selected. + + + true + + @@ -280,6 +244,78 @@ + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + User Interface + + + + + + + + + 0 + 0 + + + + Language (needs restart): + + + + + + + + + + + + true + + + Sorting Mode + + + + + + By last launched + + + sortingModeGroup + + + + + + + By name + + + sortingModeGroup + + + + + + @@ -427,6 +463,247 @@ + + + Java + + + + + + Memory + + + + + + The maximum amount of memory Minecraft is allowed to use. + + + MB + + + 512 + + + 65536 + + + 128 + + + 1024 + + + + + + + Minimum memory allocation: + + + + + + + Maximum memory allocation: + + + + + + + The amount of memory Minecraft is started with. + + + MB + + + 256 + + + 65536 + + + 128 + + + 256 + + + + + + + PermGen: + + + + + + + The amount of memory available to store loaded Java classes. + + + MB + + + 64 + + + 999999999 + + + 8 + + + 64 + + + + + + + + + + Java Settings + + + + + + + 0 + 0 + + + + Java path: + + + + + + + + 0 + 0 + + + + Auto-detect... + + + + + + + + 0 + 0 + + + + Test + + + + + + + + 0 + 0 + + + + JVM arguments: + + + + + + + + + + + + + 0 + 0 + + + + + 28 + 16777215 + + + + ... + + + + + + + + + + + + + + + Custom Commands + + + + + + Post-exit command: + + + + + + + Pre-launch command: + + + + + + + + + + + + + + + + + 0 + 0 + + + + Pre-launch command runs before the instance launches and post-exit command runs after it exits. Both will be run in MultiMC's working directory with INST_ID, INST_DIR, and INST_NAME as environment variables. + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + Network settings. @@ -586,229 +863,6 @@ - - - Java - - - - - - Memory - - - - - - 512 - - - 65536 - - - 128 - - - 1024 - - - - - - - Minimum memory allocation: - - - - - - - Maximum memory allocation: - - - - - - - 256 - - - 65536 - - - 128 - - - 256 - - - - - - - PermGen: - - - - - - - 64 - - - 999999999 - - - 8 - - - 64 - - - - - - - - - - Java Settings - - - - - - - 0 - 0 - - - - Java path: - - - - - - - - 0 - 0 - - - - Auto-detect... - - - - - - - - 0 - 0 - - - - Test - - - - - - - - 0 - 0 - - - - JVM arguments: - - - - - - - - - - - - - 0 - 0 - - - - - 28 - 16777215 - - - - ... - - - - - - - - - - - - - - - Custom Commands - - - - - - Post-exit command: - - - - - - - Pre-launch command: - - - - - - - - - - - - - - - - - 0 - 0 - - - - Pre-launch command runs before the instance launches and post-exit command runs after it exits. Both will be run in MultiMC's working directory with INST_ID, INST_DIR, and INST_NAME as environment variables. - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - true - - - - - @@ -827,20 +881,6 @@ buttonBox sortLastLaunchedBtn sortByNameBtn - autoUpdateCheckBox - trackFtbBox - ftbLauncherBox - ftbLauncherBrowseBtn - ftbBox - ftbBrowseBtn - instDirTextBox - instDirBrowseBtn - modsDirTextBox - modsDirBrowseBtn - lwjglDirTextBox - lwjglDirBrowseBtn - iconsDirTextBox - iconsDirBrowseBtn jsonEditorTextBox jsonEditorBrowseBtn maximizedCheckBox diff --git a/logic/BaseInstance.cpp b/logic/BaseInstance.cpp index ac66a8d5..222004a3 100644 --- a/logic/BaseInstance.cpp +++ b/logic/BaseInstance.cpp @@ -26,6 +26,7 @@ #include "overridesetting.h" #include "pathutils.h" +#include #include "lists/MinecraftVersionList.h" #include "logic/icons/IconList.h" @@ -81,6 +82,7 @@ BaseInstance::BaseInstance(BaseInstancePrivate *d_in, const QString &rootDir, settings().registerSetting("OverrideConsole", false); settings().registerOverride(globalSettings->getSetting("ShowConsole")); settings().registerOverride(globalSettings->getSetting("AutoCloseConsole")); + settings().registerOverride(globalSettings->getSetting("LogPrePostOutput")); } void BaseInstance::iconUpdated(QString key) @@ -248,8 +250,19 @@ void BaseInstance::setName(QString val) d->m_settings->set("name", val); emit propertiesChanged(this); } + QString BaseInstance::name() const { I_D(BaseInstance); return d->m_settings->get("name").toString(); } + +QString BaseInstance::windowTitle() const +{ + return "MultiMC: " + name(); +} + +QStringList BaseInstance::extraArguments() const +{ + return Util::Commandline::splitArgs(settings().get("JvmArgs").toString()); +} diff --git a/logic/BaseInstance.h b/logic/BaseInstance.h index 01d6dc7d..a861e9b2 100644 --- a/logic/BaseInstance.h +++ b/logic/BaseInstance.h @@ -57,7 +57,7 @@ public: /// The instance's ID. The ID SHALL be determined by MMC internally. The ID IS guaranteed to /// be unique. - QString id() const; + virtual QString id() const; /// get the type of this instance QString instanceType() const; @@ -71,6 +71,9 @@ public: QString name() const; void setName(QString val); + /// Value used for instance window titles + QString windowTitle() const; + QString iconKey() const; void setIconKey(QString val); @@ -81,6 +84,8 @@ public: void setGroupInitial(QString val); void setGroupPost(QString val); + QStringList extraArguments() const; + virtual QString intendedVersionId() const = 0; virtual bool setIntendedVersionId(QString version) = 0; diff --git a/logic/BaseVersion.h b/logic/BaseVersion.h index 1864c94c..43f5942a 100644 --- a/logic/BaseVersion.h +++ b/logic/BaseVersion.h @@ -39,6 +39,15 @@ struct BaseVersion * the kind of version this is (Stable, Beta, Snapshot, whatever) */ virtual QString typeString() const = 0; + + virtual bool operator<(BaseVersion &a) + { + return name() < a.name(); + }; + virtual bool operator>(BaseVersion &a) + { + return name() > a.name(); + }; }; typedef std::shared_ptr BaseVersionPtr; diff --git a/logic/JavaChecker.cpp b/logic/JavaChecker.cpp index 6ee7b4cf..b87ee3d5 100644 --- a/logic/JavaChecker.cpp +++ b/logic/JavaChecker.cpp @@ -20,6 +20,9 @@ void JavaChecker::performCheck() process->setArguments(args); process->setProgram(path); process->setProcessChannelMode(QProcess::SeparateChannels); + QLOG_DEBUG() << "Running java checker!"; + QLOG_DEBUG() << "Java: " + path; + QLOG_DEBUG() << "Args: {" + args.join("|") + "}"; connect(process.get(), SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(finished(int, QProcess::ExitStatus))); @@ -42,15 +45,19 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) result.path = path; result.id = id; } + QLOG_DEBUG() << "Java checker finished with status " << status << " exit code " << exitcode; if (status == QProcess::CrashExit || exitcode == 1) { + QLOG_DEBUG() << "Java checker failed!"; emit checkFinished(result); return; } bool success = true; QString p_stdout = _process->readAllStandardOutput(); + QLOG_DEBUG() << p_stdout; + QMap results; QStringList lines = p_stdout.split("\n", QString::SkipEmptyParts); for(QString line : lines) @@ -70,6 +77,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) if(!results.contains("os.arch") || !results.contains("java.version") || !success) { + QLOG_DEBUG() << "Java checker failed - couldn't extract required information."; emit checkFinished(result); return; } @@ -84,7 +92,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) result.mojangPlatform = is_64 ? "64" : "32"; result.realPlatform = os_arch; result.javaVersion = java_version; - + QLOG_DEBUG() << "Java checker succeeded."; emit checkFinished(result); } @@ -93,7 +101,7 @@ void JavaChecker::error(QProcess::ProcessError err) if(err == QProcess::FailedToStart) { killTimer.stop(); - + QLOG_DEBUG() << "Java checker has failed to start."; JavaCheckResult result; { result.path = path; @@ -110,6 +118,7 @@ void JavaChecker::timeout() // NO MERCY. NO ABUSE. if(process) { + QLOG_DEBUG() << "Java checker has been killed by timeout."; process->kill(); } } diff --git a/logic/LegacyFTBInstance.cpp b/logic/LegacyFTBInstance.cpp index 84d5a900..6c6bd10b 100644 --- a/logic/LegacyFTBInstance.cpp +++ b/logic/LegacyFTBInstance.cpp @@ -14,3 +14,8 @@ bool LegacyFTBInstance::menuActionEnabled(QString action_name) const { return false; } + +QString LegacyFTBInstance::id() const +{ + return "FTB/" + BaseInstance::id(); +} diff --git a/logic/LegacyFTBInstance.h b/logic/LegacyFTBInstance.h index 2ae72797..70f60535 100644 --- a/logic/LegacyFTBInstance.h +++ b/logic/LegacyFTBInstance.h @@ -10,4 +10,5 @@ public: QObject *parent = 0); virtual QString getStatusbarDescription(); virtual bool menuActionEnabled(QString action_name) const; + virtual QString id() const; }; diff --git a/logic/LegacyInstance.cpp b/logic/LegacyInstance.cpp index 5ab19fc9..2828bcbf 100644 --- a/logic/LegacyInstance.cpp +++ b/logic/LegacyInstance.cpp @@ -47,7 +47,7 @@ std::shared_ptr LegacyInstance::doUpdate(bool only_prepare) // make sure the jar mods list is initialized by asking for it. auto list = jarModList(); // create an update task - return std::shared_ptr (new LegacyUpdate(this, only_prepare , this)); + return std::shared_ptr(new LegacyUpdate(this, only_prepare, this)); } MinecraftProcess *LegacyInstance::prepareForLaunch(MojangAccountPtr account) @@ -58,58 +58,27 @@ MinecraftProcess *LegacyInstance::prepareForLaunch(MojangAccountPtr account) auto pixmap = icon.pixmap(128, 128); pixmap.save(PathCombine(minecraftRoot(), "icon.png"), "PNG"); - // extract the legacy launcher - QString launcherJar = PathCombine(MMC->bin(), "jars", "MultiMCLauncher.jar"); - - // set the process arguments + // create the launch script + QString launchScript; { - QStringList args; - // window size - QString windowSize; + QString windowParams; if (settings().get("LaunchMaximized").toBool()) - windowSize = "max"; + windowParams = "max"; else - windowSize = QString("%1x%2").arg(settings().get("MinecraftWinWidth").toInt()).arg( + windowParams = QString("%1x%2").arg(settings().get("MinecraftWinWidth").toInt()).arg( settings().get("MinecraftWinHeight").toInt()); - // window title - QString windowTitle; - windowTitle.append("MultiMC: ").append(name()); - - // Java arguments - args.append(Util::Commandline::splitArgs(settings().get("JvmArgs").toString())); - -#ifdef OSX - // OSX dock icon and name - args << "-Xdock:icon=icon.png"; - args << QString("-Xdock:name=\"%1\"").arg(windowTitle); -#endif - QString lwjgl = QDir(MMC->settings()->get("LWJGLDir").toString() + "/" + lwjglVersion()) .absolutePath(); - - // launcher arguments - args << QString("-Xms%1m").arg(settings().get("MinMemAlloc").toInt()); - args << QString("-Xmx%1m").arg(settings().get("MaxMemAlloc").toInt()); - args << QString("-XX:PermSize=%1m").arg(settings().get("PermGen").toInt()); -/** -* HACK: Stupid hack for Intel drivers. -* See: https://mojang.atlassian.net/browse/MCL-767 -*/ -#ifdef Q_OS_WIN32 - args << QString("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_" - "minecraft.exe.heapdump"); -#endif - - args << "-jar" << launcherJar; - args << account->currentProfile()->name; - args << account->sessionId(); - args << windowTitle; - args << windowSize; - args << lwjgl; - proc->setArguments(args); + launchScript += "userName " + account->currentProfile()->name + "\n"; + launchScript += "sessionId " + account->sessionId() + "\n"; + launchScript += "windowTitle " + windowTitle() + "\n"; + launchScript += "windowParams " + windowParams + "\n"; + launchScript += "lwjgl " + lwjgl + "\n"; + launchScript += "launch legacy\n"; } + proc->setLaunchScript(launchScript); // set the process work path proc->setWorkdir(minecraftRoot()); diff --git a/logic/MinecraftProcess.cpp b/logic/MinecraftProcess.cpp index 209929b7..84610021 100644 --- a/logic/MinecraftProcess.cpp +++ b/logic/MinecraftProcess.cpp @@ -14,14 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "MultiMC.h" #include "MinecraftProcess.h" #include #include #include -//#include #include +#include #include "BaseInstance.h" @@ -42,6 +43,7 @@ MinecraftProcess::MinecraftProcess(BaseInstance *inst) : m_instance(inst) #ifdef LINUX // Strip IBus + // IBus is a Linux IME framework. For some reason, it breaks MC? if (env.value("XMODIFIERS").contains(IBUS)) env.insert("XMODIFIERS", env.value("XMODIFIERS").replace(IBUS, "")); #endif @@ -57,11 +59,15 @@ MinecraftProcess::MinecraftProcess(BaseInstance *inst) : m_instance(inst) // std channels connect(this, SIGNAL(readyReadStandardError()), SLOT(on_stdErr())); connect(this, SIGNAL(readyReadStandardOutput()), SLOT(on_stdOut())); -} -void MinecraftProcess::setArguments(QStringList args) -{ - m_args = args; + // Log prepost launch command output (can be disabled.) + if (m_instance->settings().get("LogPrePostOutput").toBool()) + { + connect(&m_prepostlaunchprocess, &QProcess::readyReadStandardError, + this, &MinecraftProcess::on_prepost_stdErr); + connect(&m_prepostlaunchprocess, &QProcess::readyReadStandardOutput, + this, &MinecraftProcess::on_prepost_stdOut); + } } void MinecraftProcess::setWorkdir(QString path) @@ -90,47 +96,145 @@ QString MinecraftProcess::censorPrivateInfo(QString in) in.replace(profileId, ""); in.replace(profileName, ""); } + + auto i = m_account->user().properties.begin(); + while (i != m_account->user().properties.end()) + { + in.replace(i.value(), "<" + i.key().toUpper() + ">"); + ++i; + } + return in; } // console window +MessageLevel::Enum MinecraftProcess::guessLevel(const QString &line, MessageLevel::Enum level) +{ + if (line.contains("[INFO]") || line.contains("[CONFIG]") || line.contains("[FINE]") || + line.contains("[FINER]") || line.contains("[FINEST]")) + level = MessageLevel::Message; + if (line.contains("[SEVERE]") || line.contains("[STDERR]")) + level = MessageLevel::Error; + if (line.contains("[WARNING]")) + level = MessageLevel::Warning; + if (line.contains("Exception in thread") || line.contains(" at ")) + level = MessageLevel::Fatal; + if (line.contains("[DEBUG]")) + level = MessageLevel::Debug; + return level; +} + +MessageLevel::Enum MinecraftProcess::getLevel(const QString &levelName) +{ + if (levelName == "MultiMC") + return MessageLevel::MultiMC; + else if (levelName == "Debug") + return MessageLevel::Debug; + else if (levelName == "Info") + return MessageLevel::Info; + else if (levelName == "Message") + return MessageLevel::Message; + else if (levelName == "Warning") + return MessageLevel::Warning; + else if (levelName == "Error") + return MessageLevel::Error; + else if (levelName == "Fatal") + return MessageLevel::Fatal; + // Skip PrePost, it's not exposed to !![]! + else + return MessageLevel::Message; +} + +void MinecraftProcess::logOutput(const QStringList &lines, + MessageLevel::Enum defaultLevel, + bool guessLevel, bool censor) +{ + for (int i = 0; i < lines.size(); ++i) + logOutput(lines[i], defaultLevel, guessLevel, censor); +} + +void MinecraftProcess::logOutput(QString line, + MessageLevel::Enum defaultLevel, + bool guessLevel, bool censor) +{ + MessageLevel::Enum level = defaultLevel; + + // Level prefix + int endmark = line.indexOf("]!"); + if (line.startsWith("!![") && endmark != -1) + { + level = getLevel(line.left(endmark).mid(3)); + line = line.mid(endmark + 2); + } + // Guess level + else if (guessLevel) + level = this->guessLevel(line, defaultLevel); + + if (censor) + line = censorPrivateInfo(line); + + emit log(line, level); +} + void MinecraftProcess::on_stdErr() { QByteArray data = readAllStandardError(); QString str = m_err_leftover + QString::fromLocal8Bit(data); - m_err_leftover.clear(); - QStringList lines = str.split("\n"); - bool complete = str.endsWith("\n"); - for (int i = 0; i < lines.size() - 1; i++) - { - QString &line = lines[i]; - emit log(censorPrivateInfo(line), getLevel(line, MessageLevel::Error)); - } - if (!complete) - m_err_leftover = lines.last(); + QStringList lines = str.split("\n"); + m_err_leftover = lines.takeLast(); + + logOutput(lines, MessageLevel::Error); } void MinecraftProcess::on_stdOut() { QByteArray data = readAllStandardOutput(); QString str = m_out_leftover + QString::fromLocal8Bit(data); - m_out_leftover.clear(); - QStringList lines = str.split("\n"); - bool complete = str.endsWith("\n"); - for (int i = 0; i < lines.size() - 1; i++) - { - QString &line = lines[i]; - emit log(censorPrivateInfo(line), getLevel(line, MessageLevel::Message)); - } - if (!complete) - m_out_leftover = lines.last(); + QStringList lines = str.split("\n"); + m_out_leftover = lines.takeLast(); + + logOutput(lines); +} + +void MinecraftProcess::on_prepost_stdErr() +{ + QByteArray data = m_prepostlaunchprocess.readAllStandardError(); + QString str = m_err_leftover + QString::fromLocal8Bit(data); + + QStringList lines = str.split("\n"); + m_err_leftover = lines.takeLast(); + + logOutput(lines, MessageLevel::PrePost, false, false); +} + +void MinecraftProcess::on_prepost_stdOut() +{ + QByteArray data = m_prepostlaunchprocess.readAllStandardOutput(); + QString str = m_out_leftover + QString::fromLocal8Bit(data); + + QStringList lines = str.split("\n"); + m_out_leftover = lines.takeLast(); + + logOutput(lines, MessageLevel::PrePost, false, false); } // exit handler void MinecraftProcess::finish(int code, ExitStatus status) { + // Flush console window + if (!m_err_leftover.isEmpty()) + { + logOutput(m_err_leftover, MessageLevel::Error); + m_err_leftover.clear(); + } + if (!m_out_leftover.isEmpty()) + { + logOutput(m_out_leftover); + m_out_leftover.clear(); + } + if (!killed) { if (status == NormalExit) @@ -153,15 +257,32 @@ void MinecraftProcess::finish(int code, ExitStatus status) m_prepostlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(code)); // run post-exit - if (!m_instance->settings().get("PostExitCommand").toString().isEmpty()) + QString postlaunch_cmd = m_instance->settings().get("PostExitCommand").toString(); + if (!postlaunch_cmd.isEmpty()) { - m_prepostlaunchprocess.start(m_instance->settings().get("PostExitCommand").toString()); + emit log(tr("Running Post-Launch command: %1").arg(postlaunch_cmd)); + m_prepostlaunchprocess.start(postlaunch_cmd); m_prepostlaunchprocess.waitForFinished(); + // Flush console window + if (!m_err_leftover.isEmpty()) + { + logOutput(m_err_leftover, MessageLevel::PrePost); + m_err_leftover.clear(); + } + if (!m_out_leftover.isEmpty()) + { + logOutput(m_out_leftover, MessageLevel::PrePost); + m_out_leftover.clear(); + } if (m_prepostlaunchprocess.exitStatus() != NormalExit) { + emit log(tr("Post-Launch command failed with code %1.\n\n").arg(m_prepostlaunchprocess.exitCode()), + MessageLevel::Error); emit postlaunch_failed(m_instance, m_prepostlaunchprocess.exitCode(), m_prepostlaunchprocess.exitStatus()); } + else + emit log(tr("Post-Launch command ran successfully.\n\n")); } m_instance->cleanupAfterRun(); emit ended(m_instance, code, status); @@ -175,27 +296,78 @@ void MinecraftProcess::killMinecraft() void MinecraftProcess::launch() { - if (!m_instance->settings().get("PreLaunchCommand").toString().isEmpty()) + emit log("MultiMC version: " + MMC->version().toString() + "\n\n"); + emit log("Minecraft folder is:\n" + workingDirectory() + "\n\n"); + + QString prelaunch_cmd = m_instance->settings().get("PreLaunchCommand").toString(); + if (!prelaunch_cmd.isEmpty()) { - m_prepostlaunchprocess.start(m_instance->settings().get("PreLaunchCommand").toString()); + // Launch + emit log(tr("Running Pre-Launch command: %1").arg(prelaunch_cmd)); + m_prepostlaunchprocess.start(prelaunch_cmd); + // Wait m_prepostlaunchprocess.waitForFinished(); + // Flush console window + if (!m_err_leftover.isEmpty()) + { + logOutput(m_err_leftover, MessageLevel::PrePost); + m_err_leftover.clear(); + } + if (!m_out_leftover.isEmpty()) + { + logOutput(m_out_leftover, MessageLevel::PrePost); + m_out_leftover.clear(); + } + // Process return values if (m_prepostlaunchprocess.exitStatus() != NormalExit) { + emit log(tr("Pre-Launch command failed with code %1.\n\n").arg(m_prepostlaunchprocess.exitCode()), + MessageLevel::Fatal); m_instance->cleanupAfterRun(); emit prelaunch_failed(m_instance, m_prepostlaunchprocess.exitCode(), m_prepostlaunchprocess.exitStatus()); return; } + else + emit log(tr("Pre-Launch command ran successfully.\n\n")); } m_instance->setLastLaunch(); + auto &settings = m_instance->settings(); + + //////////// java arguments //////////// + QStringList args; + { + // custom args go first. we want to override them if we have our own here. + args.append(m_instance->extraArguments()); + + // OSX dock icon and name + #ifdef OSX + args << "-Xdock:icon=icon.png"; + args << QString("-Xdock:name=\"%1\"").arg(m_instance->windowTitle()); + #endif + + // HACK: Stupid hack for Intel drivers. See: https://mojang.atlassian.net/browse/MCL-767 + #ifdef Q_OS_WIN32 + args << QString("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_" + "minecraft.exe.heapdump"); + #endif + + args << QString("-Xms%1m").arg(settings.get("MinMemAlloc").toInt()); + args << QString("-Xmx%1m").arg(settings.get("MaxMemAlloc").toInt()); + args << QString("-XX:PermSize=%1m").arg(settings.get("PermGen").toInt()); + if(!m_nativeFolder.isEmpty()) + args << QString("-Djava.library.path=%1").arg(m_nativeFolder); + args << "-jar" << PathCombine(MMC->bin(), "jars", "NewLaunch.jar"); + } - emit log(QString("Minecraft folder is: '%1'").arg(workingDirectory())); QString JavaPath = m_instance->settings().get("JavaPath").toString(); - emit log(QString("Java path: '%1'").arg(JavaPath)); - QString allArgs = m_args.join("' '"); - emit log(QString("Arguments: '%1'").arg(censorPrivateInfo(allArgs))); - start(JavaPath, m_args); + emit log("Java path is:\n" + JavaPath + "\n\n"); + QString allArgs = args.join(", "); + emit log("Java Arguments:\n[" + censorPrivateInfo(allArgs) + "]\n\n"); + + // instantiate the launcher part + start(JavaPath, args); if (!waitForStarted()) { //: Error message displayed if instace can't start @@ -204,21 +376,7 @@ void MinecraftProcess::launch() emit launch_failed(m_instance); return; } -} - -MessageLevel::Enum MinecraftProcess::getLevel(const QString &line, MessageLevel::Enum level) -{ - - if (line.contains("[INFO]") || line.contains("[CONFIG]") || line.contains("[FINE]") || - line.contains("[FINER]") || line.contains("[FINEST]")) - level = MessageLevel::Message; - if (line.contains("[SEVERE]") || line.contains("[STDERR]")) - level = MessageLevel::Error; - if (line.contains("[WARNING]")) - level = MessageLevel::Warning; - if (line.contains("Exception in thread") || line.contains(" at ")) - level = MessageLevel::Fatal; - if (line.contains("[DEBUG]")) - level = MessageLevel::Debug; - return level; + // send the launch script to the launcher part + QByteArray bytes = launchScript.toUtf8(); + writeData(bytes.constData(), bytes.length()); } diff --git a/logic/MinecraftProcess.h b/logic/MinecraftProcess.h index bd0151cc..70e5df52 100644 --- a/logic/MinecraftProcess.h +++ b/logic/MinecraftProcess.h @@ -18,7 +18,7 @@ #pragma once #include - +#include #include "BaseInstance.h" /** @@ -31,11 +31,12 @@ enum Enum { MultiMC, /**< MultiMC Messages */ Debug, /**< Debug Messages */ - Info, /**< Info Messages */ + Info, /**< Info Messages */ Message, /**< Standard Messages */ Warning, /**< Warnings */ Error, /**< Errors */ - Fatal /**< Fatal Errors */ + Fatal, /**< Fatal Errors */ + PrePost, /**< Pre/Post Launch command output */ }; } @@ -65,7 +66,15 @@ public: void setWorkdir(QString path); - void setArguments(QStringList args); + void setLaunchScript(QString script) + { + launchScript = script; + } + + void setNativeFolder(QString natives) + { + m_nativeFolder = natives; + } void killMinecraft(); @@ -104,21 +113,30 @@ signals: protected: BaseInstance *m_instance = nullptr; - QStringList m_args; QString m_err_leftover; QString m_out_leftover; QProcess m_prepostlaunchprocess; bool killed = false; MojangAccountPtr m_account; + QString launchScript; + QString m_nativeFolder; protected slots: void finish(int, QProcess::ExitStatus status); void on_stdErr(); void on_stdOut(); + void on_prepost_stdOut(); + void on_prepost_stdErr(); + void logOutput(const QStringList &lines, + MessageLevel::Enum defaultLevel = MessageLevel::Message, + bool guessLevel = true, bool censor = true); + void logOutput(QString line, + MessageLevel::Enum defaultLevel = MessageLevel::Message, + bool guessLevel = true, bool censor = true); private: QString censorPrivateInfo(QString in); - MessageLevel::Enum getLevel(const QString &message, MessageLevel::Enum defaultLevel); - + MessageLevel::Enum guessLevel(const QString &message, MessageLevel::Enum defaultLevel); + MessageLevel::Enum getLevel(const QString &levelName); }; diff --git a/logic/NagUtils.cpp b/logic/NagUtils.cpp index 6f81b3c7..c963a98a 100644 --- a/logic/NagUtils.cpp +++ b/logic/NagUtils.cpp @@ -23,15 +23,15 @@ void checkJVMArgs(QString jvmargs, QWidget *parent) if (jvmargs.contains("-XX:PermSize=") || jvmargs.contains(QRegExp("-Xm[sx]"))) { CustomMessageBox::selectable( - parent, parent->tr("JVM arguments warning"), - parent->tr("You tried to manually set a JVM memory option (using " - " \"-XX:PermSize\", \"-Xmx\" or \"-Xms\") - there" - " are dedicated boxes for these in the settings (Java" - " tab, in the Memory group at the top).\n" - "Your manual settings will be overridden by the" - " dedicated options.\n" - "This message will be displayed until you remove them" - " from the JVM arguments."), + parent, QObject::tr("JVM arguments warning"), + QObject::tr("You tried to manually set a JVM memory option (using " + " \"-XX:PermSize\", \"-Xmx\" or \"-Xms\") - there" + " are dedicated boxes for these in the settings (Java" + " tab, in the Memory group at the top).\n" + "Your manual settings will be overridden by the" + " dedicated options.\n" + "This message will be displayed until you remove them" + " from the JVM arguments."), QMessageBox::Warning)->exec(); } } diff --git a/logic/OneSixFTBInstance.cpp b/logic/OneSixFTBInstance.cpp index 4bb5cf42..e50a5b53 100644 --- a/logic/OneSixFTBInstance.cpp +++ b/logic/OneSixFTBInstance.cpp @@ -92,6 +92,11 @@ OneSixFTBInstance::OneSixFTBInstance(const QString &rootDir, SettingsObject *set } } +QString OneSixFTBInstance::id() const +{ + return "FTB/" + BaseInstance::id(); +} + QString OneSixFTBInstance::getStatusbarDescription() { return "OneSix FTB: " + intendedVersionId(); diff --git a/logic/OneSixFTBInstance.h b/logic/OneSixFTBInstance.h index 7600090c..dc028819 100644 --- a/logic/OneSixFTBInstance.h +++ b/logic/OneSixFTBInstance.h @@ -15,6 +15,8 @@ public: virtual std::shared_ptr doUpdate(bool only_prepare) override; + virtual QString id() const; + private: std::shared_ptr m_forge; }; diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index 2392c683..3cfc1c76 100644 --- a/logic/OneSixInstance.cpp +++ b/logic/OneSixInstance.cpp @@ -13,12 +13,14 @@ * limitations under the License. */ +#include "MultiMC.h" #include "OneSixInstance.h" #include "OneSixInstance_p.h" #include "OneSixUpdate.h" #include "MinecraftProcess.h" #include "OneSixVersion.h" #include "JavaChecker.h" +#include "logic/icons/IconList.h" #include #include @@ -27,6 +29,7 @@ #include "gui/dialogs/OneSixModEditDialog.h" #include "logger/QsLog.h" #include "logic/assets/AssetsUtils.h" +#include OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *setting_obj, QObject *parent) @@ -40,7 +43,7 @@ OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *setting_o std::shared_ptr OneSixInstance::doUpdate(bool only_prepare) { - return std::shared_ptr (new OneSixUpdate(this, only_prepare)); + return std::shared_ptr(new OneSixUpdate(this, only_prepare)); } QString replaceTokensIn(QString text, QMap with) @@ -78,47 +81,50 @@ QDir OneSixInstance::reconstructAssets(std::shared_ptr version) QFile indexFile(indexPath); QDir virtualRoot(PathCombine(virtualDir.path(), version->assets)); - if(!indexFile.exists()) + if (!indexFile.exists()) { QLOG_ERROR() << "No assets index file" << indexPath << "; can't reconstruct assets"; return virtualRoot; } - QLOG_DEBUG() << "reconstructAssets" << assetsDir.path() << indexDir.path() << objectDir.path() << virtualDir.path() << virtualRoot.path(); + QLOG_DEBUG() << "reconstructAssets" << assetsDir.path() << indexDir.path() + << objectDir.path() << virtualDir.path() << virtualRoot.path(); AssetsIndex index; bool loadAssetsIndex = AssetsUtils::loadAssetsIndexJson(indexPath, &index); - if(loadAssetsIndex) + if (loadAssetsIndex && index.isVirtual) { - if(index.isVirtual) + QLOG_INFO() << "Reconstructing virtual assets folder at" << virtualRoot.path(); + + for (QString map : index.objects.keys()) { - QLOG_INFO() << "Reconstructing virtual assets folder at" << virtualRoot.path(); + AssetObject asset_object = index.objects.value(map); + QString target_path = PathCombine(virtualRoot.path(), map); + QFile target(target_path); - for(QString map : index.objects.keys()) + QString tlk = asset_object.hash.left(2); + + QString original_path = + PathCombine(PathCombine(objectDir.path(), tlk), asset_object.hash); + QFile original(original_path); + if(!original.exists()) + continue; + if (!target.exists()) { - AssetObject asset_object = index.objects.value(map); - QString target_path = PathCombine(virtualRoot.path(), map); - QFile target(target_path); + QFileInfo info(target_path); + QDir target_dir = info.dir(); + // QLOG_DEBUG() << target_dir; + if (!target_dir.exists()) + QDir("").mkpath(target_dir.path()); - QString tlk = asset_object.hash.left(2); - - QString original_path = PathCombine(PathCombine(objectDir.path(), tlk), asset_object.hash); - QFile original(original_path); - if(!target.exists()) - { - QFileInfo info(target_path); - QDir target_dir = info.dir(); - //QLOG_DEBUG() << target_dir; - if(!target_dir.exists()) QDir("").mkpath(target_dir.path()); - - bool couldCopy = original.copy(target_path); - QLOG_DEBUG() << " Copying" << original_path << "to" << target_path << QString::number(couldCopy);// << original.errorString(); - } + bool couldCopy = original.copy(target_path); + QLOG_DEBUG() << " Copying" << original_path << "to" << target_path + << QString::number(couldCopy); // << original.errorString(); } - - // TODO: Write last used time to virtualRoot/.lastused } + + // TODO: Write last used time to virtualRoot/.lastused } return virtualRoot; @@ -155,7 +161,7 @@ QStringList OneSixInstance::processMinecraftArgs(MojangAccountPtr account) auto user = account->user(); QJsonObject userAttrs; - for(auto key: user.properties.keys()) + for (auto key : user.properties.keys()) { auto array = QJsonArray::fromStringList(user.properties.values(key)); userAttrs.insert(key, array); @@ -180,71 +186,56 @@ MinecraftProcess *OneSixInstance::prepareForLaunch(MojangAccountPtr account) { I_D(OneSixInstance); - QString natives_dir_raw = PathCombine(instanceRoot(), "natives/"); + QIcon icon = MMC->icons()->getIcon(iconKey()); + auto pixmap = icon.pixmap(128, 128); + pixmap.save(PathCombine(minecraftRoot(), "icon.png"), "PNG"); auto version = d->version; if (!version) return nullptr; - - QStringList args; - args.append(Util::Commandline::splitArgs(settings().get("JvmArgs").toString())); - args << QString("-Xms%1m").arg(settings().get("MinMemAlloc").toInt()); - args << QString("-Xmx%1m").arg(settings().get("MaxMemAlloc").toInt()); - args << QString("-XX:PermSize=%1m").arg(settings().get("PermGen").toInt()); - -/** - * HACK: Stupid hack for Intel drivers. - * See: https://mojang.atlassian.net/browse/MCL-767 - */ -#ifdef Q_OS_WIN32 - args << QString("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_" - "minecraft.exe.heapdump"); -#endif - - QDir natives_dir(natives_dir_raw); - args << QString("-Djava.library.path=%1").arg(natives_dir.absolutePath()); - QString classPath; + QString launchScript; { auto libs = version->getActiveNormalLibs(); for (auto lib : libs) { QFileInfo fi(QString("libraries/") + lib->storagePath()); - classPath.append(fi.absoluteFilePath()); -#ifdef Q_OS_WIN32 - classPath.append(';'); -#else - classPath.append(':'); -#endif + launchScript += "cp " + fi.absoluteFilePath() + "\n"; } QString targetstr = "versions/" + version->id + "/" + version->id + ".jar"; QFileInfo fi(targetstr); - classPath.append(fi.absoluteFilePath()); + launchScript += "cp " + fi.absoluteFilePath() + "\n"; } - if (classPath.size()) + launchScript += "mainClass " + version->mainClass + "\n"; + + for (auto param : processMinecraftArgs(account)) { - args << "-cp"; - args << classPath; + launchScript += "param " + param + "\n"; } - args << version->mainClass; - args.append(processMinecraftArgs(account)); // Set the width and height for 1.6 instances bool maximize = settings().get("LaunchMaximized").toBool(); if (maximize) { // this is probably a BAD idea - // args << QString("--fullscreen"); + // launchScript += "param --fullscreen\n"; } else { - args << QString("--width") << settings().get("MinecraftWinWidth").toString(); - args << QString("--height") << settings().get("MinecraftWinHeight").toString(); + launchScript += + "param --width\nparam " + settings().get("MinecraftWinWidth").toString() + "\n"; + launchScript += + "param --height\nparam " + settings().get("MinecraftWinHeight").toString() + "\n"; } + QDir natives_dir(PathCombine(instanceRoot(), "natives/")); + launchScript += "windowTitle " + windowTitle() + "\n"; + launchScript += "natives " + natives_dir.absolutePath() + "\n"; + launchScript += "launch onesix\n"; // create the process and set its parameters MinecraftProcess *proc = new MinecraftProcess(this); - proc->setArguments(args); proc->setWorkdir(minecraftRoot()); + proc->setLaunchScript(launchScript); + // proc->setNativeFolder(natives_dir.absolutePath()); return proc; } diff --git a/logic/OneSixLibrary.cpp b/logic/OneSixLibrary.cpp index 4b6ed9dc..d1eceb0e 100644 --- a/logic/OneSixLibrary.cpp +++ b/logic/OneSixLibrary.cpp @@ -19,6 +19,9 @@ #include "OneSixRule.h" #include "OpSys.h" #include "logic/net/URLConstants.h" +#include +#include +#include "logger/QsLog.h" void OneSixLibrary::finalize() { @@ -133,6 +136,90 @@ QString OneSixLibrary::hint() return m_hint; } +bool OneSixLibrary::filesExist() +{ + QString storage = storagePath(); + if (storage.contains("${arch}")) + { + QString cooked_storage = storage; + cooked_storage.replace("${arch}", "32"); + QFileInfo info32(PathCombine("libraries", cooked_storage)); + if (!info32.exists()) + { + return false; + } + cooked_storage = storage; + cooked_storage.replace("${arch}", "64"); + QFileInfo info64(PathCombine("libraries", cooked_storage)); + if (!info64.exists()) + { + return false; + } + } + else + { + QFileInfo info(PathCombine("libraries", storage)); + if (!info.exists()) + { + return false; + } + } + return true; +} + +bool OneSixLibrary::extractTo(QString target_dir) +{ + QString storage = storagePath(); + if (storage.contains("${arch}")) + { + QString cooked_storage = storage; + cooked_storage.replace("${arch}", "32"); + QString origin = PathCombine("libraries", cooked_storage); + QString target_dir_cooked = PathCombine(target_dir, "32"); + if(!ensureFolderPathExists(target_dir_cooked)) + { + QLOG_ERROR() << "Couldn't create folder " + target_dir_cooked; + return false; + } + if (JlCompress::extractWithExceptions(origin, target_dir_cooked, extract_excludes) + .isEmpty()) + { + QLOG_ERROR() << "Couldn't extract " + origin; + return false; + } + cooked_storage = storage; + cooked_storage.replace("${arch}", "64"); + origin = PathCombine("libraries", cooked_storage); + target_dir_cooked = PathCombine(target_dir, "32"); + if(!ensureFolderPathExists(target_dir_cooked)) + { + QLOG_ERROR() << "Couldn't create folder " + target_dir_cooked; + return false; + } + if (JlCompress::extractWithExceptions(origin, target_dir_cooked, extract_excludes) + .isEmpty()) + { + QLOG_ERROR() << "Couldn't extract " + origin; + return false; + } + } + else + { + if(!ensureFolderPathExists(target_dir)) + { + QLOG_ERROR() << "Couldn't create folder " + target_dir; + return false; + } + QString path = PathCombine("libraries", storage); + if (JlCompress::extractWithExceptions(path, target_dir, extract_excludes).isEmpty()) + { + QLOG_ERROR() << "Couldn't extract " + path; + return false; + } + } + return true; +} + QJsonObject OneSixLibrary::toJson() { QJsonObject libRoot; diff --git a/logic/OneSixLibrary.h b/logic/OneSixLibrary.h index 3f0bc83d..227cdbef 100644 --- a/logic/OneSixLibrary.h +++ b/logic/OneSixLibrary.h @@ -126,4 +126,7 @@ public: /// set a hint about how to treat the library. This is an MMC extension. void setHint(QString hint); QString hint(); + + bool extractTo(QString target_dir); + bool filesExist(); }; diff --git a/logic/OneSixUpdate.cpp b/logic/OneSixUpdate.cpp index 4d93477a..0119ab07 100644 --- a/logic/OneSixUpdate.cpp +++ b/logic/OneSixUpdate.cpp @@ -54,17 +54,7 @@ void OneSixUpdate::executeTask() if (m_only_prepare) { - /* - * FIXME: in offline mode, do not proceed! - */ - setStatus(tr("Testing the Java installation...")); - QString java_path = m_inst->settings().get("JavaPath").toString(); - - checker.reset(new JavaChecker()); - connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this, - SLOT(checkFinishedOffline(JavaCheckResult))); - checker->path = java_path; - checker->performCheck(); + prepareForLaunch(); return; } @@ -83,46 +73,8 @@ void OneSixUpdate::executeTask() } else { - checkJavaOnline(); - } -} - -void OneSixUpdate::checkJavaOnline() -{ - setStatus(tr("Testing the Java installation...")); - QString java_path = m_inst->settings().get("JavaPath").toString(); - - checker.reset(new JavaChecker()); - connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this, - SLOT(checkFinishedOnline(JavaCheckResult))); - checker->path = java_path; - checker->performCheck(); -} - -void OneSixUpdate::checkFinishedOnline(JavaCheckResult result) -{ - if (result.valid) - { - java_is_64bit = result.is_64bit; jarlibStart(); } - else - { - emitFailed("The java binary doesn't work. Check the settings and correct the problem"); - } -} - -void OneSixUpdate::checkFinishedOffline(JavaCheckResult result) -{ - if (result.valid) - { - java_is_64bit = result.is_64bit; - prepareForLaunch(); - } - else - { - emitFailed("The java binary doesn't work. Check the settings and correct the problem"); - } } void OneSixUpdate::versionFileStart() @@ -130,7 +82,8 @@ void OneSixUpdate::versionFileStart() QLOG_INFO() << m_inst->name() << ": getting version file."; setStatus(tr("Getting the version files from Mojang...")); - QString urlstr = "http://" + URLConstants::AWS_DOWNLOAD_VERSIONS + targetVersion->descriptor() + "/" + targetVersion->descriptor() + ".json"; + QString urlstr = "http://" + URLConstants::AWS_DOWNLOAD_VERSIONS + + targetVersion->descriptor() + "/" + targetVersion->descriptor() + ".json"; auto job = new NetJob("Version index"); job->addNetAction(ByteArrayDownload::make(QUrl(urlstr))); specificVersionDownloadJob.reset(job); @@ -186,7 +139,7 @@ void OneSixUpdate::versionFileFinished() } inst->reloadFullVersion(); - checkJavaOnline(); + jarlibStart(); } void OneSixUpdate::versionFileFailed() @@ -230,7 +183,7 @@ void OneSixUpdate::assetIndexFinished() { emitFailed("Failed to read the assets index!"); } - + QList dls; for (auto object : index.objects.values()) { @@ -245,17 +198,17 @@ void OneSixUpdate::assetIndexFinished() dls.append(objectDL); } } - if(dls.size()) + if (dls.size()) { setStatus(tr("Getting the assets files from Mojang...")); auto job = new NetJob("Assets for " + inst->name()); - for(auto dl: dls) + for (auto dl : dls) job->addNetAction(dl); jarlibDownloadJob.reset(job); connect(jarlibDownloadJob.get(), SIGNAL(succeeded()), SLOT(assetsFinished())); connect(jarlibDownloadJob.get(), SIGNAL(failed()), SLOT(assetsFailed())); connect(jarlibDownloadJob.get(), SIGNAL(progress(qint64, qint64)), - SIGNAL(progress(qint64, qint64))); + SIGNAL(progress(qint64, qint64))); jarlibDownloadJob->start(); return; } @@ -277,8 +230,6 @@ void OneSixUpdate::assetsFailed() emitFailed("Failed to download assets!"); } - - void OneSixUpdate::jarlibStart() { setStatus(tr("Getting the library files from Mojang...")); @@ -318,24 +269,37 @@ void OneSixUpdate::jarlibStart() { if (lib->hint() == "local") continue; - QString subst = java_is_64bit ? "64" : "32"; - QString storage = lib->storagePath(); - QString dl = lib->downloadUrl(); - storage.replace("${arch}", subst); - dl.replace("${arch}", subst); + QString raw_storage = lib->storagePath(); + QString raw_dl = lib->downloadUrl(); - auto entry = metacache->resolveEntry("libraries", storage); - if (entry->stale) + auto f = [&](QString storage, QString dl) { - if (lib->hint() == "forge-pack-xz") + auto entry = metacache->resolveEntry("libraries", storage); + if (entry->stale) { - ForgeLibs.append(ForgeXzDownload::make(storage, entry)); - } - else - { - jarlibDownloadJob->addNetAction(CacheDownload::make(dl, entry)); + if (lib->hint() == "forge-pack-xz") + { + ForgeLibs.append(ForgeXzDownload::make(storage, entry)); + } + else + { + jarlibDownloadJob->addNetAction(CacheDownload::make(dl, entry)); + } } + }; + if (raw_storage.contains("${arch}")) + { + QString cooked_storage = raw_storage; + QString cooked_dl = raw_dl; + f(cooked_storage.replace("${arch}", "32"), cooked_dl.replace("${arch}", "32")); + cooked_storage = raw_storage; + cooked_dl = raw_dl; + f(cooked_storage.replace("${arch}", "64"), cooked_dl.replace("${arch}", "64")); + } + else + { + f(raw_storage, raw_dl); } } // TODO: think about how to propagate this from the original json file... or IF AT ALL @@ -376,7 +340,6 @@ void OneSixUpdate::prepareForLaunch() // delete any leftovers, if they are present. onesix_inst->cleanupAfterRun(); - // Acquire swag QString natives_dir_raw = PathCombine(onesix_inst->instanceRoot(), "natives/"); auto version = onesix_inst->getFullVersion(); if (!version) @@ -385,38 +348,30 @@ void OneSixUpdate::prepareForLaunch() "it or changing the version."); return; } - auto libs_to_extract = version->getActiveNativeLibs(); - - // Acquire bag - bool success = ensureFolderPathExists(natives_dir_raw); - if (!success) + /* + * emitFailed("Could not create the native library folder:\n" + natives_dir_raw + + "\nMake sure MultiMC has appropriate permissions and there is enough + space " + "on the storage device."); + */ + for (auto lib : version->getActiveNativeLibs()) { - emitFailed("Could not create the native library folder:\n" + natives_dir_raw + - "\nMake sure MultiMC has appropriate permissions and there is enough space " - "on the storage device."); - return; - } - - // Put swag in the bag - QString subst = java_is_64bit ? "64" : "32"; - for (auto lib : libs_to_extract) - { - QString storage = lib->storagePath(); - storage.replace("${arch}", subst); - - QString path = "libraries/" + storage; - QLOG_INFO() << "Will extract " << path.toLocal8Bit(); - if (JlCompress::extractWithExceptions(path, natives_dir_raw, lib->extract_excludes) - .isEmpty()) + if (!lib->filesExist()) { - emitFailed( - "Could not extract the native library:\n" + path + - "\nMake sure MultiMC has appropriate permissions and there is enough space " - "on the storage device."); + emitFailed("Native library is missing some files:\n" + lib->storagePath() + + "\n\nRun the instance at least once in online mode to get all the " + "required files."); + return; + } + if (!lib->extractTo(natives_dir_raw)) + { + emitFailed("Could not extract the native library:\n" + lib->storagePath() + " to " + + natives_dir_raw + + "\n\nMake sure MultiMC has appropriate permissions and there is enough " + "space on the storage device."); return; } } - // Show them your war face! emitSucceeded(); } diff --git a/logic/OneSixUpdate.h b/logic/OneSixUpdate.h index 00b769c7..bc717a94 100644 --- a/logic/OneSixUpdate.h +++ b/logic/OneSixUpdate.h @@ -21,7 +21,6 @@ #include "logic/net/NetJob.h" #include "logic/tasks/Task.h" -#include "logic/JavaChecker.h" class MinecraftVersion; class BaseInstance; @@ -50,10 +49,6 @@ slots: void assetsFinished(); void assetsFailed(); - void checkJavaOnline(); - void checkFinishedOnline(JavaCheckResult result); - void checkFinishedOffline(JavaCheckResult result); - // extract the appropriate libraries void prepareForLaunch(); @@ -65,7 +60,4 @@ private: std::shared_ptr targetVersion; BaseInstance *m_inst = nullptr; bool m_only_prepare = false; - std::shared_ptr checker; - - bool java_is_64bit = false; }; diff --git a/logic/SkinUtils.h b/logic/SkinUtils.h index 324f86b8..64353b72 100644 --- a/logic/SkinUtils.h +++ b/logic/SkinUtils.h @@ -19,5 +19,5 @@ namespace SkinUtils { -QPixmap getFaceFromCache(QString username, int height = 48, int width = 48); +QPixmap getFaceFromCache(QString username, int height = 64, int width = 64); } diff --git a/logic/auth/MojangAccount.cpp b/logic/auth/MojangAccount.cpp index a462eda5..f41985ec 100644 --- a/logic/auth/MojangAccount.cpp +++ b/logic/auth/MojangAccount.cpp @@ -198,7 +198,11 @@ void MojangAccount::authFailed(QString reason) { // This is emitted when the yggdrasil tasks time out or are cancelled. // -> we treat the error as no-op - if (reason != "Yggdrasil task cancelled.") + if (reason == "Yggdrasil task cancelled.") + { + // do nothing + } + else { m_online = false; m_accessToken = QString(); diff --git a/logic/icons/IconList.cpp b/logic/icons/IconList.cpp index cda2db7b..d76e6fbb 100644 --- a/logic/icons/IconList.cpp +++ b/logic/icons/IconList.cpp @@ -336,6 +336,23 @@ QIcon IconList::getIcon(QString key) return QIcon(); } +QIcon IconList::getBigIcon(QString key) +{ + int icon_index = getIconIndex(key); + + if (icon_index == -1) + key = "infinity"; + + // Fallback for icons that don't exist. + icon_index = getIconIndex(key); + + if (icon_index == -1) + return QIcon(); + + QPixmap bigone = icons[icon_index].icon().pixmap(256,256).scaled(256,256); + return QIcon(bigone); +} + int IconList::getIconIndex(QString key) { if (key == "default") diff --git a/logic/icons/IconList.h b/logic/icons/IconList.h index 322411d1..4ee3f782 100644 --- a/logic/icons/IconList.h +++ b/logic/icons/IconList.h @@ -34,6 +34,7 @@ public: virtual ~IconList() {}; QIcon getIcon(QString key); + QIcon getBigIcon(QString key); int getIconIndex(QString key); virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; diff --git a/logic/lists/ForgeVersionList.cpp b/logic/lists/ForgeVersionList.cpp index 56eca744..4902dc64 100644 --- a/logic/lists/ForgeVersionList.cpp +++ b/logic/lists/ForgeVersionList.cpp @@ -187,7 +187,7 @@ bool ForgeListLoadTask::parseForgeList(QList &out) QByteArray data; { auto dlJob = listDownload; - auto filename = std::dynamic_pointer_cast(dlJob)->m_target_path; + auto filename = std::dynamic_pointer_cast(dlJob)->getTargetFilepath(); QFile listFile(filename); if (!listFile.open(QIODevice::ReadOnly)) { @@ -303,7 +303,7 @@ bool ForgeListLoadTask::parseForgeGradleList(QList &out) QByteArray data; { auto dlJob = gradleListDownload; - auto filename = std::dynamic_pointer_cast(dlJob)->m_target_path; + auto filename = std::dynamic_pointer_cast(dlJob)->getTargetFilepath(); QFile listFile(filename); if (!listFile.open(QIODevice::ReadOnly)) { @@ -404,12 +404,8 @@ void ForgeListLoadTask::listDownloaded() { return; } - - qSort(list.begin(), list.end(), [](const BaseVersionPtr & p1, const BaseVersionPtr & p2) - { - // TODO better comparison (takes major/minor/build number into account) - return p1->name() > p2->name(); - }); + std::sort(list.begin(), list.end(), [](const BaseVersionPtr & l, const BaseVersionPtr & r) + { return (*l > *r); }); m_list->updateListData(list); diff --git a/logic/lists/ForgeVersionList.h b/logic/lists/ForgeVersionList.h index 924084ae..b19d3f56 100644 --- a/logic/lists/ForgeVersionList.h +++ b/logic/lists/ForgeVersionList.h @@ -29,25 +29,38 @@ typedef std::shared_ptr ForgeVersionPtr; struct ForgeVersion : public BaseVersion { - virtual QString descriptor() + virtual QString descriptor() override { return filename; } ; - virtual QString name() + virtual QString name() override { return "Forge " + jobbuildver; } ; - virtual QString typeString() const + virtual QString typeString() const override { if (installer_url.isEmpty()) return "Universal"; else return "Installer"; } - ; + virtual bool operator<(BaseVersion &a) override + { + ForgeVersion *pa = dynamic_cast(&a); + if(!pa) + return true; + return m_buildnr < pa->m_buildnr; + } + virtual bool operator>(BaseVersion &a) override + { + ForgeVersion *pa = dynamic_cast(&a); + if(!pa) + return false; + return m_buildnr > pa->m_buildnr; + } int m_buildnr = 0; QString universal_url; QString changelog_url; diff --git a/logic/lists/InstanceList.cpp b/logic/lists/InstanceList.cpp index bfd183d9..0d4eab95 100644 --- a/logic/lists/InstanceList.cpp +++ b/logic/lists/InstanceList.cpp @@ -308,45 +308,52 @@ void InstanceList::loadForgeInstances(QMap groupMap) return; } dir.cd("ModPacks"); - auto fpath = dir.absoluteFilePath("modpacks.xml"); - QFile f(fpath); - QLOG_INFO() << "Discovering FTB instances -- " << fpath; - if (!f.open(QFile::ReadOnly)) - return; - - // read the FTB packs XML. - QXmlStreamReader reader(&f); - while (!reader.atEnd()) + auto allFiles = dir.entryList(QDir::Readable | QDir::Files, QDir::Name); + for(auto filename: allFiles) { - switch (reader.readNext()) + if(!filename.endsWith(".xml")) + continue; + auto fpath = dir.absoluteFilePath(filename); + QFile f(fpath); + QLOG_INFO() << "Discovering FTB instances -- " << fpath; + if (!f.open(QFile::ReadOnly)) + continue; + + // read the FTB packs XML. + QXmlStreamReader reader(&f); + while (!reader.atEnd()) { - case QXmlStreamReader::StartElement: - { - if (reader.name() == "modpack") + switch (reader.readNext()) { - QXmlStreamAttributes attrs = reader.attributes(); - FTBRecord record; - record.dir = attrs.value("dir").toString(); - QDir test(dataDir.absoluteFilePath(record.dir)); - if(!test.exists()) - continue; - record.name = attrs.value("name").toString(); - record.logo = attrs.value("logo").toString(); - record.mcVersion = attrs.value("mcVersion").toString(); - record.description = attrs.value("description").toString(); - records.append(record); + case QXmlStreamReader::StartElement: + { + if (reader.name() == "modpack") + { + QXmlStreamAttributes attrs = reader.attributes(); + FTBRecord record; + record.dir = attrs.value("dir").toString(); + QDir test(dataDir.absoluteFilePath(record.dir)); + if(!test.exists()) + continue; + record.name = attrs.value("name").toString(); + record.logo = attrs.value("logo").toString(); + record.mcVersion = attrs.value("mcVersion").toString(); + record.description = attrs.value("description").toString(); + records.append(record); + } + break; + } + case QXmlStreamReader::EndElement: + break; + case QXmlStreamReader::Characters: + break; + default: + break; } - break; - } - case QXmlStreamReader::EndElement: - break; - case QXmlStreamReader::Characters: - break; - default: - break; } + f.close(); } - f.close(); + if(!records.size()) { QLOG_INFO() << "No FTB instances to load."; diff --git a/logic/net/CacheDownload.cpp b/logic/net/CacheDownload.cpp index 6eadae39..d2a9bdee 100644 --- a/logic/net/CacheDownload.cpp +++ b/logic/net/CacheDownload.cpp @@ -33,25 +33,44 @@ CacheDownload::CacheDownload(QUrl url, MetaEntryPtr entry) void CacheDownload::start() { + m_status = Job_InProgress; if (!m_entry->stale) { + m_status = Job_Finished; emit succeeded(m_index_within_job); return; } - m_output_file.setFileName(m_target_path); + // create a new save file + m_output_file.reset(new QSaveFile(m_target_path)); + // if there already is a file and md5 checking is in effect and it can be opened if (!ensureFilePathExists(m_target_path)) { + QLOG_ERROR() << "Could not create folder for " + m_target_path; + m_status = Job_Failed; + emit failed(m_index_within_job); + return; + } + if (!m_output_file->open(QIODevice::WriteOnly)) + { + QLOG_ERROR() << "Could not open " + m_target_path + " for writing"; + m_status = Job_Failed; emit failed(m_index_within_job); return; } QLOG_INFO() << "Downloading " << m_url.toString(); QNetworkRequest request(m_url); - if (m_entry->remote_changed_timestamp.size()) - request.setRawHeader(QString("If-Modified-Since").toLatin1(), - m_entry->remote_changed_timestamp.toLatin1()); - if (m_entry->etag.size()) - request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->etag.toLatin1()); + + // check file consistency first. + QFile current(m_target_path); + if(current.exists() && current.size() != 0) + { + if (m_entry->remote_changed_timestamp.size()) + request.setRawHeader(QString("If-Modified-Since").toLatin1(), + m_entry->remote_changed_timestamp.toLatin1()); + if (m_entry->etag.size()) + request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->etag.toLatin1()); + } request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Cached)"); @@ -77,76 +96,74 @@ void CacheDownload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) void CacheDownload::downloadError(QNetworkReply::NetworkError error) { // error happened during download. - QLOG_ERROR() << "Failed" << m_url.toString() << "with reason" << error; + QLOG_ERROR() << "Failed " << m_url.toString() << " with reason " << error; m_status = Job_Failed; } void CacheDownload::downloadFinished() { // if the download succeeded - if (m_status != Job_Failed) + if (m_status == Job_Failed) { - - // nothing went wrong... - m_status = Job_Finished; - if (m_output_file.isOpen()) - { - // save the data to the downloadable if we aren't saving to file - m_output_file.close(); - m_entry->md5sum = md5sum.result().toHex().constData(); - } - else - { - if (m_output_file.open(QIODevice::ReadOnly)) - { - m_entry->md5sum = - QCryptographicHash::hash(m_output_file.readAll(), QCryptographicHash::Md5) - .toHex() - .constData(); - m_output_file.close(); - } - } - QFileInfo output_file_info(m_target_path); - - m_entry->etag = m_reply->rawHeader("ETag").constData(); - if (m_reply->hasRawHeader("Last-Modified")) - { - m_entry->remote_changed_timestamp = m_reply->rawHeader("Last-Modified").constData(); - } - m_entry->local_changed_timestamp = - output_file_info.lastModified().toUTC().toMSecsSinceEpoch(); - m_entry->stale = false; - MMC->metacache()->updateEntry(m_entry); - - m_reply.reset(); - emit succeeded(m_index_within_job); - return; - } - // else the download failed - else - { - m_output_file.close(); - m_output_file.remove(); + m_output_file->cancelWriting(); m_reply.reset(); emit failed(m_index_within_job); return; } -} -void CacheDownload::downloadReadyRead() -{ - if (!m_output_file.isOpen()) + // if we wrote any data to the save file, we try to commit the data to the real file. + if (wroteAnyData) { - if (!m_output_file.open(QIODevice::WriteOnly)) + // nothing went wrong... + if (m_output_file->commit()) { - /* - * Can't open the file... the job failed - */ - m_reply->abort(); + m_status = Job_Finished; + m_entry->md5sum = md5sum.result().toHex().constData(); + } + else + { + QLOG_ERROR() << "Failed to commit changes to " << m_target_path; + m_output_file->cancelWriting(); + m_reply.reset(); + m_status = Job_Failed; emit failed(m_index_within_job); return; } } + else + { + m_status = Job_Finished; + } + + // then get rid of the save file + m_output_file.reset(); + + QFileInfo output_file_info(m_target_path); + + m_entry->etag = m_reply->rawHeader("ETag").constData(); + if (m_reply->hasRawHeader("Last-Modified")) + { + m_entry->remote_changed_timestamp = m_reply->rawHeader("Last-Modified").constData(); + } + m_entry->local_changed_timestamp = + output_file_info.lastModified().toUTC().toMSecsSinceEpoch(); + m_entry->stale = false; + MMC->metacache()->updateEntry(m_entry); + + m_reply.reset(); + emit succeeded(m_index_within_job); + return; +} + +void CacheDownload::downloadReadyRead() +{ QByteArray ba = m_reply->readAll(); md5sum.addData(ba); - m_output_file.write(ba); + if (m_output_file->write(ba) != ba.size()) + { + QLOG_ERROR() << "Failed writing into " + m_target_path; + m_status = Job_Failed; + m_reply->abort(); + emit failed(m_index_within_job); + } + wroteAnyData = true; } diff --git a/logic/net/CacheDownload.h b/logic/net/CacheDownload.h index e25aecd2..154f5988 100644 --- a/logic/net/CacheDownload.h +++ b/logic/net/CacheDownload.h @@ -17,29 +17,34 @@ #include "NetAction.h" #include "HttpMetaCache.h" -#include -#include +#include +#include typedef std::shared_ptr CacheDownloadPtr; class CacheDownload : public NetAction { Q_OBJECT -public: +private: MetaEntryPtr m_entry; /// if saving to file, use the one specified in this string QString m_target_path; /// this is the output file, if any - QFile m_output_file; + std::shared_ptr m_output_file; /// the hash-as-you-download QCryptographicHash md5sum; + bool wroteAnyData = false; + public: explicit CacheDownload(QUrl url, MetaEntryPtr entry); static CacheDownloadPtr make(QUrl url, MetaEntryPtr entry) { return CacheDownloadPtr(new CacheDownload(url, entry)); } - + QString getTargetFilepath() + { + return m_target_path; + } protected slots: virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); diff --git a/logic/net/URLConstants.h b/logic/net/URLConstants.h index 9579198d..8cb1f3fd 100644 --- a/logic/net/URLConstants.h +++ b/logic/net/URLConstants.h @@ -31,4 +31,6 @@ const QString SKINS_BASE("skins.minecraft.net/MinecraftSkins/"); const QString AUTH_BASE("authserver.mojang.com/"); const QString FORGE_LEGACY_URL("http://files.minecraftforge.net/minecraftforge/json"); const QString FORGE_GRADLE_URL("http://files.minecraftforge.net/maven/net/minecraftforge/forge/json"); +const QString MOJANG_STATUS_URL("http://status.mojang.com/check"); +const QString MOJANG_STATUS_NEWS_URL("http://status.mojang.com/news"); } diff --git a/logic/status/StatusChecker.cpp b/logic/status/StatusChecker.cpp new file mode 100644 index 00000000..66f800ae --- /dev/null +++ b/logic/status/StatusChecker.cpp @@ -0,0 +1,137 @@ +/* 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 "StatusChecker.h" + +#include + +#include +#include + +#include + +StatusChecker::StatusChecker() +{ + +} + +void StatusChecker::reloadStatus() +{ + if (isLoadingStatus()) + { + // QLOG_INFO() << "Ignored request to reload status. Currently reloading already."; + return; + } + + // QLOG_INFO() << "Reloading status."; + + NetJob* job = new NetJob("Status JSON"); + job->addNetAction(ByteArrayDownload::make(URLConstants::MOJANG_STATUS_URL)); + QObject::connect(job, &NetJob::succeeded, this, &StatusChecker::statusDownloadFinished); + QObject::connect(job, &NetJob::failed, this, &StatusChecker::statusDownloadFailed); + m_statusNetJob.reset(job); + job->start(); +} + +void StatusChecker::statusDownloadFinished() +{ + QLOG_DEBUG() << "Finished loading status JSON."; + + QByteArray data; + { + ByteArrayDownloadPtr dl = std::dynamic_pointer_cast(m_statusNetJob->first()); + data = dl->m_data; + m_statusNetJob.reset(); + } + + QJsonParseError jsonError; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); + + if (jsonError.error != QJsonParseError::NoError) + { + fail("Error parsing status JSON:" + jsonError.errorString()); + return; + } + + if (!jsonDoc.isArray()) + { + fail("Error parsing status JSON: JSON root is not an array"); + return; + } + + QJsonArray root = jsonDoc.array(); + + for(auto status = root.begin(); status != root.end(); ++status) + { + QVariantMap map = (*status).toObject().toVariantMap(); + + for (QVariantMap::const_iterator iter = map.begin(); iter != map.end(); ++iter) + { + QString key = iter.key(); + QVariant value = iter.value(); + + if(value.type() == QVariant::Type::String) + { + m_statusEntries.insert(key, value.toString()); + //QLOG_DEBUG() << "Status JSON object: " << key << m_statusEntries[key]; + } + else + { + fail("Malformed status JSON: expected status type to be a string."); + return; + } + } + } + + succeed(); +} + +void StatusChecker::statusDownloadFailed() +{ + fail("Failed to load status JSON."); +} + + +QMap StatusChecker::getStatusEntries() const +{ + return m_statusEntries; +} + +bool StatusChecker::isLoadingStatus() const +{ + return m_statusNetJob.get() != nullptr; +} + +QString StatusChecker::getLastLoadErrorMsg() const +{ + return m_lastLoadError; +} + +void StatusChecker::succeed() +{ + m_lastLoadError = ""; + QLOG_DEBUG() << "Status loading succeeded."; + m_statusNetJob.reset(); + emit statusLoaded(); +} + +void StatusChecker::fail(const QString& errorMsg) +{ + m_lastLoadError = errorMsg; + QLOG_DEBUG() << "Failed to load status:" << errorMsg; + m_statusNetJob.reset(); + emit statusLoadingFailed(errorMsg); +} + diff --git a/logic/status/StatusChecker.h b/logic/status/StatusChecker.h new file mode 100644 index 00000000..1cb01836 --- /dev/null +++ b/logic/status/StatusChecker.h @@ -0,0 +1,57 @@ +/* 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 +#include +#include + +#include + +class StatusChecker : public QObject +{ + Q_OBJECT +public: + StatusChecker(); + + QString getLastLoadErrorMsg() const; + + bool isStatusLoaded() const; + + bool isLoadingStatus() const; + + QMap getStatusEntries() const; + + void Q_SLOT reloadStatus(); + +signals: + void statusLoaded(); + void statusLoadingFailed(QString errorMsg); + +protected slots: + void statusDownloadFinished(); + void statusDownloadFailed(); + +protected: + QMap m_statusEntries; + NetJobPtr m_statusNetJob; + bool m_loadedStatus; + QString m_lastLoadError; + + void Q_SLOT succeed(); + void Q_SLOT fail(const QString& errorMsg); +}; + diff --git a/logic/updater/NotificationChecker.cpp b/logic/updater/NotificationChecker.cpp index b2d67632..191e90a3 100644 --- a/logic/updater/NotificationChecker.cpp +++ b/logic/updater/NotificationChecker.cpp @@ -55,7 +55,7 @@ void NotificationChecker::downloadSucceeded(int) { m_entries.clear(); - QFile file(m_download->m_output_file.fileName()); + QFile file(m_download->getTargetFilepath()); if (file.open(QFile::ReadOnly)) { QJsonArray root = QJsonDocument::fromJson(file.readAll()).array(); diff --git a/logic/updater/UpdateChecker.cpp b/logic/updater/UpdateChecker.cpp index 8a280dd1..8e2aa8b3 100644 --- a/logic/updater/UpdateChecker.cpp +++ b/logic/updater/UpdateChecker.cpp @@ -30,7 +30,6 @@ UpdateChecker::UpdateChecker() { - m_currentChannel = VERSION_CHANNEL; m_channelListUrl = CHANLIST_URL; m_updateChecking = false; m_chanListLoading = false; diff --git a/logic/updater/UpdateChecker.h b/logic/updater/UpdateChecker.h index 7840cedc..3b0ee28d 100644 --- a/logic/updater/UpdateChecker.h +++ b/logic/updater/UpdateChecker.h @@ -27,7 +27,6 @@ public: UpdateChecker(); void checkForUpdate(bool notifyNoUpdate); - void setCurrentChannel(const QString &channel) { m_currentChannel = channel; } void setChannelListUrl(const QString &url) { m_channelListUrl = url; } /*! @@ -83,7 +82,6 @@ private: QString m_repoUrl; QString m_channelListUrl; - QString m_currentChannel; QList m_channels; diff --git a/main.cpp b/main.cpp index 57131942..181d7299 100644 --- a/main.cpp +++ b/main.cpp @@ -4,6 +4,7 @@ int main_gui(MultiMC &app) { // show main window + QIcon::setThemeName("multimc"); MainWindow mainWin; mainWin.restoreState(QByteArray::fromBase64(MMC->settings()->get("MainWindowState").toByteArray())); mainWin.restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("MainWindowGeometry").toByteArray())); @@ -18,8 +19,9 @@ int main(int argc, char *argv[]) // initialize Qt MultiMC app(argc, argv); - Q_INIT_RESOURCE(graphics); - Q_INIT_RESOURCE(generated); + Q_INIT_RESOURCE(instances); + Q_INIT_RESOURCE(multimc); + Q_INIT_RESOURCE(backgrounds); switch (app.status()) { diff --git a/MultiMC.icns b/resources/MultiMC.icns similarity index 100% rename from MultiMC.icns rename to resources/MultiMC.icns diff --git a/resources/icons/MultiMC.ico b/resources/MultiMC.ico similarity index 100% rename from resources/icons/MultiMC.ico rename to resources/MultiMC.ico diff --git a/MultiMC.manifest b/resources/MultiMC.manifest similarity index 100% rename from MultiMC.manifest rename to resources/MultiMC.manifest diff --git a/resources/XdgIcon.theme b/resources/XdgIcon.theme deleted file mode 100644 index ad26482e..00000000 --- a/resources/XdgIcon.theme +++ /dev/null @@ -1,12 +0,0 @@ -[Icon Theme] -Name=MultiMC -Comment=MultiMC Default Icons -Inherits=default -Directories=scalable/apps - -[scalable/apps] -Size=48 -Type=scalable -MinSize=1 -MaxSize=512 -Context=Applications diff --git a/resources/backgrounds/backgrounds.qrc b/resources/backgrounds/backgrounds.qrc new file mode 100644 index 00000000..55de139e --- /dev/null +++ b/resources/backgrounds/backgrounds.qrc @@ -0,0 +1,6 @@ + + + + catbgrnd2.png + + diff --git a/resources/catbgrnd2.png b/resources/backgrounds/catbgrnd2.png similarity index 100% rename from resources/catbgrnd2.png rename to resources/backgrounds/catbgrnd2.png diff --git a/resources/icons/toolbar/Cat.png b/resources/icons/toolbar/Cat.png deleted file mode 100644 index 4fcda3ea..00000000 Binary files a/resources/icons/toolbar/Cat.png and /dev/null differ diff --git a/resources/icons/toolbar/InstCopy.png b/resources/icons/toolbar/InstCopy.png deleted file mode 100644 index c8f9db41..00000000 Binary files a/resources/icons/toolbar/InstCopy.png and /dev/null differ diff --git a/resources/icons/toolbar/refresh.png b/resources/icons/toolbar/refresh.png deleted file mode 100644 index 734729bf..00000000 Binary files a/resources/icons/toolbar/refresh.png and /dev/null differ diff --git a/resources/icons/instances/brick.png b/resources/instances/brick.png similarity index 100% rename from resources/icons/instances/brick.png rename to resources/instances/brick.png diff --git a/resources/icons/instances/chicken.png b/resources/instances/chicken.png similarity index 100% rename from resources/icons/instances/chicken.png rename to resources/instances/chicken.png diff --git a/resources/icons/instances/chicken128.png b/resources/instances/chicken128.png similarity index 100% rename from resources/icons/instances/chicken128.png rename to resources/instances/chicken128.png diff --git a/resources/icons/instances/creeper.png b/resources/instances/creeper.png similarity index 100% rename from resources/icons/instances/creeper.png rename to resources/instances/creeper.png diff --git a/resources/icons/instances/creeper128.png b/resources/instances/creeper128.png similarity index 100% rename from resources/icons/instances/creeper128.png rename to resources/instances/creeper128.png diff --git a/resources/icons/instances/derp.png b/resources/instances/derp.png similarity index 100% rename from resources/icons/instances/derp.png rename to resources/instances/derp.png diff --git a/resources/icons/instances/diamond.png b/resources/instances/diamond.png similarity index 100% rename from resources/icons/instances/diamond.png rename to resources/instances/diamond.png diff --git a/resources/icons/instances/dirt.png b/resources/instances/dirt.png similarity index 100% rename from resources/icons/instances/dirt.png rename to resources/instances/dirt.png diff --git a/resources/icons/instances/enderman.png b/resources/instances/enderman.png similarity index 100% rename from resources/icons/instances/enderman.png rename to resources/instances/enderman.png diff --git a/resources/icons/instances/enderpearl.png b/resources/instances/enderpearl.png similarity index 100% rename from resources/icons/instances/enderpearl.png rename to resources/instances/enderpearl.png diff --git a/resources/icons/instances/enderpearl128.png b/resources/instances/enderpearl128.png similarity index 100% rename from resources/icons/instances/enderpearl128.png rename to resources/instances/enderpearl128.png diff --git a/resources/icons/instances/ftb_glow.png b/resources/instances/ftb_glow.png similarity index 100% rename from resources/icons/instances/ftb_glow.png rename to resources/instances/ftb_glow.png diff --git a/resources/icons/instances/ftb_glow128.png b/resources/instances/ftb_glow128.png similarity index 100% rename from resources/icons/instances/ftb_glow128.png rename to resources/instances/ftb_glow128.png diff --git a/resources/icons/instances/ftb_logo.png b/resources/instances/ftb_logo.png similarity index 100% rename from resources/icons/instances/ftb_logo.png rename to resources/instances/ftb_logo.png diff --git a/resources/icons/instances/ftb_logo128.png b/resources/instances/ftb_logo128.png similarity index 100% rename from resources/icons/instances/ftb_logo128.png rename to resources/instances/ftb_logo128.png diff --git a/resources/icons/instances/gear.png b/resources/instances/gear.png similarity index 100% rename from resources/icons/instances/gear.png rename to resources/instances/gear.png diff --git a/resources/icons/instances/gear128.png b/resources/instances/gear128.png similarity index 100% rename from resources/icons/instances/gear128.png rename to resources/instances/gear128.png diff --git a/resources/icons/instances/gold.png b/resources/instances/gold.png similarity index 100% rename from resources/icons/instances/gold.png rename to resources/instances/gold.png diff --git a/resources/icons/instances/grass.png b/resources/instances/grass.png similarity index 100% rename from resources/icons/instances/grass.png rename to resources/instances/grass.png diff --git a/resources/icons/instances/herobrine.png b/resources/instances/herobrine.png similarity index 100% rename from resources/icons/instances/herobrine.png rename to resources/instances/herobrine.png diff --git a/resources/icons/instances/herobrine128.png b/resources/instances/herobrine128.png similarity index 100% rename from resources/icons/instances/herobrine128.png rename to resources/instances/herobrine128.png diff --git a/resources/icons/instances/infinity.png b/resources/instances/infinity.png similarity index 100% rename from resources/icons/instances/infinity.png rename to resources/instances/infinity.png diff --git a/resources/icons/instances/infinity128.png b/resources/instances/infinity128.png similarity index 100% rename from resources/icons/instances/infinity128.png rename to resources/instances/infinity128.png diff --git a/resources/instances/instances.qrc b/resources/instances/instances.qrc new file mode 100644 index 00000000..ec3cdf21 --- /dev/null +++ b/resources/instances/instances.qrc @@ -0,0 +1,35 @@ + + + + + brick.png + diamond.png + dirt.png + gold.png + grass.png + stone.png + tnt.png + iron.png + planks.png + + + derp.png + enderman.png + + + chicken128.png + creeper128.png + enderpearl128.png + ftb_glow128.png + ftb_logo128.png + gear128.png + herobrine128.png + infinity128.png + magitech128.png + meat128.png + netherstar128.png + skeleton128.png + squarecreeper128.png + steve128.png + + diff --git a/resources/icons/instances/iron.png b/resources/instances/iron.png similarity index 100% rename from resources/icons/instances/iron.png rename to resources/instances/iron.png diff --git a/resources/icons/instances/magitech.png b/resources/instances/magitech.png similarity index 100% rename from resources/icons/instances/magitech.png rename to resources/instances/magitech.png diff --git a/resources/icons/instances/magitech128.png b/resources/instances/magitech128.png similarity index 100% rename from resources/icons/instances/magitech128.png rename to resources/instances/magitech128.png diff --git a/resources/icons/instances/meat.png b/resources/instances/meat.png similarity index 100% rename from resources/icons/instances/meat.png rename to resources/instances/meat.png diff --git a/resources/icons/instances/meat128.png b/resources/instances/meat128.png similarity index 100% rename from resources/icons/instances/meat128.png rename to resources/instances/meat128.png diff --git a/resources/icons/instances/netherstar.png b/resources/instances/netherstar.png similarity index 100% rename from resources/icons/instances/netherstar.png rename to resources/instances/netherstar.png diff --git a/resources/icons/instances/netherstar128.png b/resources/instances/netherstar128.png similarity index 100% rename from resources/icons/instances/netherstar128.png rename to resources/instances/netherstar128.png diff --git a/resources/icons/instances/planks.png b/resources/instances/planks.png similarity index 100% rename from resources/icons/instances/planks.png rename to resources/instances/planks.png diff --git a/resources/icons/instances/skeleton.png b/resources/instances/skeleton.png similarity index 100% rename from resources/icons/instances/skeleton.png rename to resources/instances/skeleton.png diff --git a/resources/icons/instances/skeleton128.png b/resources/instances/skeleton128.png similarity index 100% rename from resources/icons/instances/skeleton128.png rename to resources/instances/skeleton128.png diff --git a/resources/icons/instances/squarecreeper.png b/resources/instances/squarecreeper.png similarity index 100% rename from resources/icons/instances/squarecreeper.png rename to resources/instances/squarecreeper.png diff --git a/resources/icons/instances/squarecreeper128.png b/resources/instances/squarecreeper128.png similarity index 100% rename from resources/icons/instances/squarecreeper128.png rename to resources/instances/squarecreeper128.png diff --git a/resources/icons/instances/steve.png b/resources/instances/steve.png similarity index 100% rename from resources/icons/instances/steve.png rename to resources/instances/steve.png diff --git a/resources/icons/instances/steve128.png b/resources/instances/steve128.png similarity index 100% rename from resources/icons/instances/steve128.png rename to resources/instances/steve128.png diff --git a/resources/icons/instances/stone.png b/resources/instances/stone.png similarity index 100% rename from resources/icons/instances/stone.png rename to resources/instances/stone.png diff --git a/resources/icons/instances/tnt.png b/resources/instances/tnt.png similarity index 100% rename from resources/icons/instances/tnt.png rename to resources/instances/tnt.png diff --git a/multimc.rc b/resources/multimc.rc similarity index 90% rename from multimc.rc rename to resources/multimc.rc index 2140e3f4..ca92e2c3 100644 --- a/multimc.rc +++ b/resources/multimc.rc @@ -3,7 +3,7 @@ #endif #include -IDI_ICON1 ICON DISCARDABLE "resources/icons/MultiMC.ico" +IDI_ICON1 ICON DISCARDABLE "MultiMC.ico" 1 RT_MANIFEST "MultiMC.manifest" VS_VERSION_INFO VERSIONINFO diff --git a/resources/multimc/16x16/about.png b/resources/multimc/16x16/about.png new file mode 100644 index 00000000..a6a986e1 Binary files /dev/null and b/resources/multimc/16x16/about.png differ diff --git a/resources/multimc/16x16/bug.png b/resources/multimc/16x16/bug.png new file mode 100644 index 00000000..0c5b78b4 Binary files /dev/null and b/resources/multimc/16x16/bug.png differ diff --git a/resources/multimc/16x16/cat.png b/resources/multimc/16x16/cat.png new file mode 100644 index 00000000..e6e31b44 Binary files /dev/null and b/resources/multimc/16x16/cat.png differ diff --git a/resources/multimc/16x16/centralmods.png b/resources/multimc/16x16/centralmods.png new file mode 100644 index 00000000..c1b91c76 Binary files /dev/null and b/resources/multimc/16x16/centralmods.png differ diff --git a/resources/multimc/16x16/checkupdate.png b/resources/multimc/16x16/checkupdate.png new file mode 100644 index 00000000..f3742058 Binary files /dev/null and b/resources/multimc/16x16/checkupdate.png differ diff --git a/resources/multimc/16x16/copy.png b/resources/multimc/16x16/copy.png new file mode 100644 index 00000000..ccaed9e1 Binary files /dev/null and b/resources/multimc/16x16/copy.png differ diff --git a/resources/multimc/16x16/help.png b/resources/multimc/16x16/help.png new file mode 100644 index 00000000..e6edf6ba Binary files /dev/null and b/resources/multimc/16x16/help.png differ diff --git a/resources/multimc/16x16/new.png b/resources/multimc/16x16/new.png new file mode 100644 index 00000000..2e56f589 Binary files /dev/null and b/resources/multimc/16x16/new.png differ diff --git a/resources/multimc/16x16/news.png b/resources/multimc/16x16/news.png new file mode 100644 index 00000000..872e85db Binary files /dev/null and b/resources/multimc/16x16/news.png differ diff --git a/resources/multimc/16x16/noaccount.png b/resources/multimc/16x16/noaccount.png new file mode 100644 index 00000000..b49bcf36 Binary files /dev/null and b/resources/multimc/16x16/noaccount.png differ diff --git a/resources/multimc/16x16/refresh.png b/resources/multimc/16x16/refresh.png new file mode 100644 index 00000000..86b6f82c Binary files /dev/null and b/resources/multimc/16x16/refresh.png differ diff --git a/resources/multimc/16x16/settings.png b/resources/multimc/16x16/settings.png new file mode 100644 index 00000000..b916cd24 Binary files /dev/null and b/resources/multimc/16x16/settings.png differ diff --git a/resources/multimc/16x16/viewfolder.png b/resources/multimc/16x16/viewfolder.png new file mode 100644 index 00000000..98b8a944 Binary files /dev/null and b/resources/multimc/16x16/viewfolder.png differ diff --git a/resources/icons/toolbar/about.png b/resources/multimc/22x22/about.png similarity index 100% rename from resources/icons/toolbar/about.png rename to resources/multimc/22x22/about.png diff --git a/resources/icons/toolbar/ReportBug.png b/resources/multimc/22x22/bug.png similarity index 100% rename from resources/icons/toolbar/ReportBug.png rename to resources/multimc/22x22/bug.png diff --git a/resources/multimc/22x22/cat.png b/resources/multimc/22x22/cat.png new file mode 100644 index 00000000..3ea7ba69 Binary files /dev/null and b/resources/multimc/22x22/cat.png differ diff --git a/resources/icons/toolbar/centralmods.png b/resources/multimc/22x22/centralmods.png similarity index 100% rename from resources/icons/toolbar/centralmods.png rename to resources/multimc/22x22/centralmods.png diff --git a/resources/icons/toolbar/checkupdate.png b/resources/multimc/22x22/checkupdate.png similarity index 100% rename from resources/icons/toolbar/checkupdate.png rename to resources/multimc/22x22/checkupdate.png diff --git a/resources/multimc/22x22/copy.png b/resources/multimc/22x22/copy.png new file mode 100644 index 00000000..ea236a24 Binary files /dev/null and b/resources/multimc/22x22/copy.png differ diff --git a/resources/icons/toolbar/help.png b/resources/multimc/22x22/help.png similarity index 100% rename from resources/icons/toolbar/help.png rename to resources/multimc/22x22/help.png diff --git a/resources/icons/toolbar/new.png b/resources/multimc/22x22/new.png similarity index 100% rename from resources/icons/toolbar/new.png rename to resources/multimc/22x22/new.png diff --git a/resources/icons/toolbar/NewsIcon.png b/resources/multimc/22x22/news.png similarity index 100% rename from resources/icons/toolbar/NewsIcon.png rename to resources/multimc/22x22/news.png diff --git a/resources/multimc/22x22/refresh.png b/resources/multimc/22x22/refresh.png new file mode 100644 index 00000000..45b5535c Binary files /dev/null and b/resources/multimc/22x22/refresh.png differ diff --git a/resources/icons/toolbar/settings.png b/resources/multimc/22x22/settings.png similarity index 100% rename from resources/icons/toolbar/settings.png rename to resources/multimc/22x22/settings.png diff --git a/resources/icons/toolbar/viewfolder.png b/resources/multimc/22x22/viewfolder.png similarity index 100% rename from resources/icons/toolbar/viewfolder.png rename to resources/multimc/22x22/viewfolder.png diff --git a/resources/multimc/24x24/cat.png b/resources/multimc/24x24/cat.png new file mode 100644 index 00000000..c93245f6 Binary files /dev/null and b/resources/multimc/24x24/cat.png differ diff --git a/resources/multimc/24x24/noaccount.png b/resources/multimc/24x24/noaccount.png new file mode 100644 index 00000000..ac12437c Binary files /dev/null and b/resources/multimc/24x24/noaccount.png differ diff --git a/resources/multimc/32x32/about.png b/resources/multimc/32x32/about.png new file mode 100644 index 00000000..5174c4f1 Binary files /dev/null and b/resources/multimc/32x32/about.png differ diff --git a/resources/multimc/32x32/bug.png b/resources/multimc/32x32/bug.png new file mode 100644 index 00000000..ada46653 Binary files /dev/null and b/resources/multimc/32x32/bug.png differ diff --git a/resources/multimc/32x32/cat.png b/resources/multimc/32x32/cat.png new file mode 100644 index 00000000..78ff98e9 Binary files /dev/null and b/resources/multimc/32x32/cat.png differ diff --git a/resources/multimc/32x32/centralmods.png b/resources/multimc/32x32/centralmods.png new file mode 100644 index 00000000..cd2b8208 Binary files /dev/null and b/resources/multimc/32x32/centralmods.png differ diff --git a/resources/multimc/32x32/checkupdate.png b/resources/multimc/32x32/checkupdate.png new file mode 100644 index 00000000..754005f9 Binary files /dev/null and b/resources/multimc/32x32/checkupdate.png differ diff --git a/resources/multimc/32x32/copy.png b/resources/multimc/32x32/copy.png new file mode 100644 index 00000000..c137b0f1 Binary files /dev/null and b/resources/multimc/32x32/copy.png differ diff --git a/resources/multimc/32x32/help.png b/resources/multimc/32x32/help.png new file mode 100644 index 00000000..b3854278 Binary files /dev/null and b/resources/multimc/32x32/help.png differ diff --git a/resources/multimc/32x32/new.png b/resources/multimc/32x32/new.png new file mode 100644 index 00000000..a3555ba4 Binary files /dev/null and b/resources/multimc/32x32/new.png differ diff --git a/resources/multimc/32x32/news.png b/resources/multimc/32x32/news.png new file mode 100644 index 00000000..c579fd44 Binary files /dev/null and b/resources/multimc/32x32/news.png differ diff --git a/resources/multimc/32x32/noaccount.png b/resources/multimc/32x32/noaccount.png new file mode 100644 index 00000000..a73afc94 Binary files /dev/null and b/resources/multimc/32x32/noaccount.png differ diff --git a/resources/multimc/32x32/refresh.png b/resources/multimc/32x32/refresh.png new file mode 100644 index 00000000..afa2a9d7 Binary files /dev/null and b/resources/multimc/32x32/refresh.png differ diff --git a/resources/multimc/32x32/settings.png b/resources/multimc/32x32/settings.png new file mode 100644 index 00000000..a9c0817c Binary files /dev/null and b/resources/multimc/32x32/settings.png differ diff --git a/resources/multimc/32x32/viewfolder.png b/resources/multimc/32x32/viewfolder.png new file mode 100644 index 00000000..74ab8fa6 Binary files /dev/null and b/resources/multimc/32x32/viewfolder.png differ diff --git a/resources/multimc/48x48/about.png b/resources/multimc/48x48/about.png new file mode 100644 index 00000000..b4ac71b8 Binary files /dev/null and b/resources/multimc/48x48/about.png differ diff --git a/resources/multimc/48x48/bug.png b/resources/multimc/48x48/bug.png new file mode 100644 index 00000000..298f9397 Binary files /dev/null and b/resources/multimc/48x48/bug.png differ diff --git a/resources/multimc/48x48/cat.png b/resources/multimc/48x48/cat.png new file mode 100644 index 00000000..25912a3c Binary files /dev/null and b/resources/multimc/48x48/cat.png differ diff --git a/resources/multimc/48x48/centralmods.png b/resources/multimc/48x48/centralmods.png new file mode 100644 index 00000000..d927e39b Binary files /dev/null and b/resources/multimc/48x48/centralmods.png differ diff --git a/resources/multimc/48x48/checkupdate.png b/resources/multimc/48x48/checkupdate.png new file mode 100644 index 00000000..2e2c7d6b Binary files /dev/null and b/resources/multimc/48x48/checkupdate.png differ diff --git a/resources/multimc/48x48/copy.png b/resources/multimc/48x48/copy.png new file mode 100644 index 00000000..ea40e34b Binary files /dev/null and b/resources/multimc/48x48/copy.png differ diff --git a/resources/multimc/48x48/help.png b/resources/multimc/48x48/help.png new file mode 100644 index 00000000..82d828fa Binary files /dev/null and b/resources/multimc/48x48/help.png differ diff --git a/resources/multimc/48x48/new.png b/resources/multimc/48x48/new.png new file mode 100644 index 00000000..a81753b3 Binary files /dev/null and b/resources/multimc/48x48/new.png differ diff --git a/resources/multimc/48x48/news.png b/resources/multimc/48x48/news.png new file mode 100644 index 00000000..0f82d857 Binary files /dev/null and b/resources/multimc/48x48/news.png differ diff --git a/resources/multimc/48x48/noaccount.png b/resources/multimc/48x48/noaccount.png new file mode 100644 index 00000000..4703796c Binary files /dev/null and b/resources/multimc/48x48/noaccount.png differ diff --git a/resources/multimc/48x48/refresh.png b/resources/multimc/48x48/refresh.png new file mode 100644 index 00000000..0b08b238 Binary files /dev/null and b/resources/multimc/48x48/refresh.png differ diff --git a/resources/multimc/48x48/settings.png b/resources/multimc/48x48/settings.png new file mode 100644 index 00000000..6674eb23 Binary files /dev/null and b/resources/multimc/48x48/settings.png differ diff --git a/resources/multimc/48x48/viewfolder.png b/resources/multimc/48x48/viewfolder.png new file mode 100644 index 00000000..0492a736 Binary files /dev/null and b/resources/multimc/48x48/viewfolder.png differ diff --git a/resources/multimc/64x64/about.png b/resources/multimc/64x64/about.png new file mode 100644 index 00000000..b83e9269 Binary files /dev/null and b/resources/multimc/64x64/about.png differ diff --git a/resources/multimc/64x64/bug.png b/resources/multimc/64x64/bug.png new file mode 100644 index 00000000..156b0315 Binary files /dev/null and b/resources/multimc/64x64/bug.png differ diff --git a/resources/multimc/64x64/cat.png b/resources/multimc/64x64/cat.png new file mode 100644 index 00000000..2cc21f80 Binary files /dev/null and b/resources/multimc/64x64/cat.png differ diff --git a/resources/multimc/64x64/centralmods.png b/resources/multimc/64x64/centralmods.png new file mode 100644 index 00000000..8831f437 Binary files /dev/null and b/resources/multimc/64x64/centralmods.png differ diff --git a/resources/multimc/64x64/checkupdate.png b/resources/multimc/64x64/checkupdate.png new file mode 100644 index 00000000..dd1e29ac Binary files /dev/null and b/resources/multimc/64x64/checkupdate.png differ diff --git a/resources/multimc/64x64/copy.png b/resources/multimc/64x64/copy.png new file mode 100644 index 00000000..d12cf9c8 Binary files /dev/null and b/resources/multimc/64x64/copy.png differ diff --git a/resources/multimc/64x64/help.png b/resources/multimc/64x64/help.png new file mode 100644 index 00000000..0f3948c2 Binary files /dev/null and b/resources/multimc/64x64/help.png differ diff --git a/resources/multimc/64x64/new.png b/resources/multimc/64x64/new.png new file mode 100644 index 00000000..c3c6796c Binary files /dev/null and b/resources/multimc/64x64/new.png differ diff --git a/resources/multimc/64x64/news.png b/resources/multimc/64x64/news.png new file mode 100644 index 00000000..e306eed3 Binary files /dev/null and b/resources/multimc/64x64/news.png differ diff --git a/resources/multimc/64x64/refresh.png b/resources/multimc/64x64/refresh.png new file mode 100644 index 00000000..8373d819 Binary files /dev/null and b/resources/multimc/64x64/refresh.png differ diff --git a/resources/multimc/64x64/settings.png b/resources/multimc/64x64/settings.png new file mode 100644 index 00000000..e3ff58fa Binary files /dev/null and b/resources/multimc/64x64/settings.png differ diff --git a/resources/multimc/64x64/viewfolder.png b/resources/multimc/64x64/viewfolder.png new file mode 100644 index 00000000..7d531f9c Binary files /dev/null and b/resources/multimc/64x64/viewfolder.png differ diff --git a/resources/icons/toolbar/NoAccount.png b/resources/multimc/8x8/noaccount.png similarity index 100% rename from resources/icons/toolbar/NoAccount.png rename to resources/multimc/8x8/noaccount.png diff --git a/resources/multimc/index.theme b/resources/multimc/index.theme new file mode 100644 index 00000000..776792b7 --- /dev/null +++ b/resources/multimc/index.theme @@ -0,0 +1,33 @@ +[Icon Theme] +Name=multimc +Comment=MultiMC Default Icons +Inherits=default +Directories=scalable/apps,8x8,16x16,22x22,24x24,32x32,48x48 + +[scalable/apps] +Size=48 +Type=scalable +MinSize=1 +MaxSize=512 +Context=Applications + +[8x8] +Size=8 + +[16x16] +Size=16 + +[22x22] +Size=22 + +[24x24] +Size=24 + +[32x32] +Size=32 + +[48x48] +Size=48 + +[64x64] +Size=64 \ No newline at end of file diff --git a/resources/multimc/multimc.qrc b/resources/multimc/multimc.qrc new file mode 100644 index 00000000..363347de --- /dev/null +++ b/resources/multimc/multimc.qrc @@ -0,0 +1,111 @@ + + + + index.theme + + scalable/apps/multimc.svg + + + scalable/console.svg + + + scalable/console_error.svg + + + 16x16/about.png + 22x22/about.png + 32x32/about.png + 48x48/about.png + 64x64/about.png + + + scalable/bug.svg + 16x16/bug.png + 22x22/bug.png + 32x32/bug.png + 48x48/bug.png + 64x64/bug.png + + + 16x16/cat.png + 22x22/cat.png + 24x24/cat.png + 32x32/cat.png + 48x48/cat.png + 64x64/cat.png + + + scalable/centralmods.svg + 16x16/centralmods.png + 22x22/centralmods.png + 32x32/centralmods.png + 48x48/centralmods.png + 64x64/centralmods.png + + + scalable/checkupdate.svg + 16x16/checkupdate.png + 22x22/checkupdate.png + 32x32/checkupdate.png + 48x48/checkupdate.png + 64x64/checkupdate.png + + + 16x16/copy.png + 22x22/copy.png + 32x32/copy.png + 48x48/copy.png + 64x64/copy.png + + + 16x16/help.png + 22x22/help.png + 32x32/help.png + 48x48/help.png + 64x64/help.png + + + 16x16/new.png + 22x22/new.png + 32x32/new.png + 48x48/new.png + 64x64/new.png + + + scalable/news.svg + 16x16/news.png + 22x22/news.png + 32x32/news.png + 48x48/news.png + 64x64/news.png + + + 16x16/refresh.png + 22x22/refresh.png + 32x32/refresh.png + 48x48/refresh.png + 64x64/refresh.png + + + 16x16/settings.png + 22x22/settings.png + 32x32/settings.png + 48x48/settings.png + 64x64/settings.png + + + scalable/viewfolder.svg + 16x16/viewfolder.png + 22x22/viewfolder.png + 32x32/viewfolder.png + 48x48/viewfolder.png + 64x64/viewfolder.png + + + 8x8/noaccount.png + 16x16/noaccount.png + 24x24/noaccount.png + 32x32/noaccount.png + 48x48/noaccount.png + + diff --git a/resources/icons/multimc.svg b/resources/multimc/scalable/apps/multimc.svg similarity index 100% rename from resources/icons/multimc.svg rename to resources/multimc/scalable/apps/multimc.svg diff --git a/resources/icons/toolbar_svg/bug.svg b/resources/multimc/scalable/bug.svg similarity index 90% rename from resources/icons/toolbar_svg/bug.svg rename to resources/multimc/scalable/bug.svg index 0534cbef..178e3c23 100644 --- a/resources/icons/toolbar_svg/bug.svg +++ b/resources/multimc/scalable/bug.svg @@ -14,11 +14,11 @@ height="32" id="svg2" version="1.1" - inkscape:version="0.48.3.1 r9886" + inkscape:version="0.48.4 r9939" sodipodi:docname="bug.svg" - inkscape:export-filename="/home/peterix/projects/MultiMC4/src/resources/tbaricons/ReportBug.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90"> + inkscape:export-filename="/home/peterix/minecraft/src/MultiMC5/resources/multimc/64x64/bug.png" + inkscape:export-xdpi="180" + inkscape:export-ydpi="180"> + + + + + + + + + unsorted + + + + + Open Clip Art Library, Source: Oxygen Icons, Source: Oxygen Icons, Source: Oxygen Icons, Source: Oxygen Icons + + + + + + + + + + + + + + image/svg+xml + + + en + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/multimc/scalable/checkupdate.svg b/resources/multimc/scalable/checkupdate.svg new file mode 100644 index 00000000..fc09cb4c --- /dev/null +++ b/resources/multimc/scalable/checkupdate.svg @@ -0,0 +1,167 @@ + + + + + + + + + + unsorted + + + + + Open Clip Art Library, Source: GNOME-Colors, Source: GNOME-Colors, Source: GNOME-Colors, Source: GNOME-Colors, Source: GNOME-Colors + + + + + + + + + + + + + + image/svg+xml + + + en + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/icons/console.svg b/resources/multimc/scalable/console.svg similarity index 100% rename from resources/icons/console.svg rename to resources/multimc/scalable/console.svg diff --git a/resources/icons/console_error.svg b/resources/multimc/scalable/console_error.svg similarity index 100% rename from resources/icons/console_error.svg rename to resources/multimc/scalable/console_error.svg diff --git a/resources/multimc/scalable/new.svg b/resources/multimc/scalable/new.svg new file mode 100644 index 00000000..c9cff358 --- /dev/null +++ b/resources/multimc/scalable/new.svg @@ -0,0 +1,127 @@ + + + + + + New Document + + + + regular + plaintext + text + document + + + + + Source: GNOME Icon Theme, Source: GNOME Icon Theme, Source: GNOME Icon Theme, Source: GNOME Icon Theme, Source: GNOME Icon Theme + + + + + Jakub Steiner + + + + + Jakub Steiner + + + + image/svg+xml + + + en + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/icons/toolbar_svg/news.svg b/resources/multimc/scalable/news.svg similarity index 100% rename from resources/icons/toolbar_svg/news.svg rename to resources/multimc/scalable/news.svg diff --git a/resources/multimc/scalable/viewfolder.svg b/resources/multimc/scalable/viewfolder.svg new file mode 100644 index 00000000..4ba0ed0a --- /dev/null +++ b/resources/multimc/scalable/viewfolder.svg @@ -0,0 +1,122 @@ + + + + + + + + + + unsorted + + + + + Open Clip Art Library, Source: Oxygen Icons, Source: Oxygen Icons, Source: Oxygen Icons, Source: Oxygen Icons + + + + + + + + + + + + + + image/svg+xml + + + en + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/icons/instances_svg/clucker.svg b/resources/sources/clucker.svg similarity index 100% rename from resources/icons/instances_svg/clucker.svg rename to resources/sources/clucker.svg diff --git a/resources/icons/instances_svg/creeper.svg b/resources/sources/creeper.svg similarity index 100% rename from resources/icons/instances_svg/creeper.svg rename to resources/sources/creeper.svg diff --git a/resources/icons/instances_svg/enderpearl.svg b/resources/sources/enderpearl.svg similarity index 100% rename from resources/icons/instances_svg/enderpearl.svg rename to resources/sources/enderpearl.svg diff --git a/resources/icons/instances_svg/ftb-glow.svg b/resources/sources/ftb-glow.svg similarity index 100% rename from resources/icons/instances_svg/ftb-glow.svg rename to resources/sources/ftb-glow.svg diff --git a/resources/icons/instances_svg/ftb-logo.svg b/resources/sources/ftb-logo.svg similarity index 100% rename from resources/icons/instances_svg/ftb-logo.svg rename to resources/sources/ftb-logo.svg diff --git a/resources/icons/instances_svg/gear.svg b/resources/sources/gear.svg similarity index 100% rename from resources/icons/instances_svg/gear.svg rename to resources/sources/gear.svg diff --git a/resources/icons/instances_svg/herobrine.svg b/resources/sources/herobrine.svg similarity index 100% rename from resources/icons/instances_svg/herobrine.svg rename to resources/sources/herobrine.svg diff --git a/resources/icons/instances_svg/magitech.svg b/resources/sources/magitech.svg similarity index 100% rename from resources/icons/instances_svg/magitech.svg rename to resources/sources/magitech.svg diff --git a/resources/icons/instances_svg/meat.svg b/resources/sources/meat.svg similarity index 100% rename from resources/icons/instances_svg/meat.svg rename to resources/sources/meat.svg diff --git a/resources/icons/instances_svg/netherstar.svg b/resources/sources/netherstar.svg similarity index 100% rename from resources/icons/instances_svg/netherstar.svg rename to resources/sources/netherstar.svg diff --git a/resources/icons/instances_svg/pskeleton.svg b/resources/sources/pskeleton.svg similarity index 100% rename from resources/icons/instances_svg/pskeleton.svg rename to resources/sources/pskeleton.svg diff --git a/resources/icons/instances_svg/skeleton.svg b/resources/sources/skeleton.svg similarity index 100% rename from resources/icons/instances_svg/skeleton.svg rename to resources/sources/skeleton.svg diff --git a/resources/icons/instances_svg/squarecreeper.svg b/resources/sources/squarecreeper.svg similarity index 100% rename from resources/icons/instances_svg/squarecreeper.svg rename to resources/sources/squarecreeper.svg diff --git a/resources/sources/status-bad.svg b/resources/sources/status-bad.svg new file mode 100644 index 00000000..54334e06 --- /dev/null +++ b/resources/sources/status-bad.svg @@ -0,0 +1,262 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/resources/sources/status-good.svg b/resources/sources/status-good.svg new file mode 100644 index 00000000..3b311806 --- /dev/null +++ b/resources/sources/status-good.svg @@ -0,0 +1,293 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/resources/sources/status-terrible.svg b/resources/sources/status-terrible.svg new file mode 100644 index 00000000..b0de7bfd --- /dev/null +++ b/resources/sources/status-terrible.svg @@ -0,0 +1,262 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/resources/icons/instances_svg/steve.svg b/resources/sources/steve.svg similarity index 100% rename from resources/icons/instances_svg/steve.svg rename to resources/sources/steve.svg diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2d851404..7aeae59f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -84,9 +84,23 @@ if(MultiMC_CODE_COVERAGE) add_custom_target(MultiMC_RUN_TESTS DEPENDS MultiMC_GENERATE_COVERAGE_HTML) endif(MultiMC_CODE_COVERAGE) +set(MultiMC_TEST_DATA_PATH "${CMAKE_CURRENT_BINARY_DIR}/data") +if(UNIX) + # on unix we get the third / from the filename + set(MultiMC_TEST_DATA_PATH "file://${MultiMC_TEST_DATA_PATH}") +else() + # we don't on windows, so we have to add it ourselves + set(MultiMC_TEST_DATA_PATH "file:///${MultiMC_TEST_DATA_PATH}") +endif() +file(GLOB data_files "data/*") +foreach(data_file ${data_files}) + get_filename_component(filename ${data_file} NAME) + configure_file( + ${data_file} + ${CMAKE_CURRENT_BINARY_DIR}/data/${filename} + @ONLY + NEWLINE_STYLE LF + ) +endforeach() -add_custom_target(MultiMC_Test_Data - ALL - COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_CURRENT_BINARY_DIR}/data - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/data ${CMAKE_CURRENT_BINARY_DIR}/data -) +configure_file(test_config.h.in test_config.h @ONLY) diff --git a/tests/TestUtil.h b/tests/TestUtil.h index 57d1fdf2..e9099b15 100644 --- a/tests/TestUtil.h +++ b/tests/TestUtil.h @@ -7,6 +7,8 @@ #include "MultiMC.h" +#include "test_config.h" + struct TestsInternal { static QByteArray readFile(const QString &fileName) diff --git a/tests/data/1.json b/tests/data/1.json index f9f99b22..0f2d6ced 100644 --- a/tests/data/1.json +++ b/tests/data/1.json @@ -8,7 +8,7 @@ "Sources": [ { "SourceType": "http", - "Url": "$PWD/tests/data/fileOneA" + "Url": "@MultiMC_TEST_DATA_PATH@/fileOneA" } ], "Executable": true, @@ -20,7 +20,7 @@ "Sources": [ { "SourceType": "http", - "Url": "$PWD/tests/data/fileTwo" + "Url": "@MultiMC_TEST_DATA_PATH@/fileTwo" } ], "Executable": false, @@ -32,7 +32,7 @@ "Sources": [ { "SourceType": "http", - "Url": "$PWD/tests/data/fileThree" + "Url": "@MultiMC_TEST_DATA_PATH@/fileThree" } ], "Executable": false, diff --git a/tests/data/2.json b/tests/data/2.json index bb59b9b6..6e2b0d3c 100644 --- a/tests/data/2.json +++ b/tests/data/2.json @@ -8,7 +8,7 @@ "Sources": [ { "SourceType": "http", - "Url": "$PWD/tests/data/fileOneB" + "Url": "@MultiMC_TEST_DATA_PATH@/fileOneB" } ], "Executable": true, @@ -20,7 +20,7 @@ "Sources": [ { "SourceType": "http", - "Url": "$PWD/tests/data/fileTwo" + "Url": "@MultiMC_TEST_DATA_PATH@/fileTwo" } ], "Executable": false, diff --git a/tests/data/channels.json b/tests/data/channels.json index d7446274..3ad504b0 100644 --- a/tests/data/channels.json +++ b/tests/data/channels.json @@ -5,13 +5,13 @@ "id": "develop", "name": "Develop", "description": "The channel called \"develop\"", - "url": "$PWD/tests/data/" + "url": "@MultiMC_TEST_DATA_PATH@" }, { "id": "stable", "name": "Stable", "description": "It's stable at least", - "url": "$PWD/tests/data/" + "url": "@MultiMC_TEST_DATA_PATH@" }, { "id": "42", diff --git a/tests/test_config.h.in b/tests/test_config.h.in new file mode 100644 index 00000000..69dd38e7 --- /dev/null +++ b/tests/test_config.h.in @@ -0,0 +1,3 @@ +#pragma once + +#define MultiMC_TEST_DATA_PATH "@MultiMC_TEST_DATA_PATH@" diff --git a/tests/tst_UpdateChecker.cpp b/tests/tst_UpdateChecker.cpp index 1e5e682f..0dcb242f 100644 --- a/tests/tst_UpdateChecker.cpp +++ b/tests/tst_UpdateChecker.cpp @@ -1,6 +1,9 @@ #include #include +#include "depends/settings/settingsobject.h" +#include "depends/settings/setting.h" + #include "TestUtil.h" #include "logic/updater/UpdateChecker.h" @@ -20,6 +23,19 @@ QDebug operator<<(QDebug dbg, const UpdateChecker::ChannelListEntry &c) return dbg.maybeSpace(); } +class ResetSetting +{ +public: + ResetSetting(std::shared_ptr setting) : setting(setting), oldValue(setting->get()) {} + ~ResetSetting() + { + setting->set(oldValue); + } + + std::shared_ptr setting; + QVariant oldValue; +}; + class UpdateCheckerTest : public QObject { Q_OBJECT @@ -76,24 +92,27 @@ slots: << true << true << (QList() - << UpdateChecker::ChannelListEntry{"develop", "Develop", "The channel called \"develop\"", "$PWD/tests/data/"} - << UpdateChecker::ChannelListEntry{"stable", "Stable", "It's stable at least", "$PWD/tests/data/"} + << UpdateChecker::ChannelListEntry{"develop", "Develop", "The channel called \"develop\"", MultiMC_TEST_DATA_PATH} + << UpdateChecker::ChannelListEntry{"stable", "Stable", "It's stable at least", MultiMC_TEST_DATA_PATH} << UpdateChecker::ChannelListEntry{"42", "The Channel", "This is the channel that is going to answer all of your questions", "https://dent.me/tea"}); } void tst_ChannelListParsing() { + ResetSetting resetUpdateChannel(MMC->settings()->getSetting("UpdateChannel")); + QFETCH(QString, channel); QFETCH(QString, channelUrl); QFETCH(bool, hasChannels); QFETCH(bool, valid); QFETCH(QList, result); + MMC->settings()->set("UpdateChannel", channel); + UpdateChecker checker; QSignalSpy channelListLoadedSpy(&checker, SIGNAL(channelListLoaded())); QVERIFY(channelListLoadedSpy.isValid()); - checker.setCurrentChannel(channel); checker.setChannelListUrl(channelUrl); checker.updateChanList(); @@ -112,8 +131,7 @@ slots: QCOMPARE(checker.hasChannels(), hasChannels); QCOMPARE(checker.getChannelList(), result); } - // FIXME: fix, comment, explain what it does. -/* + void tst_UpdateChecking_data() { QTest::addColumn("channel"); @@ -126,19 +144,19 @@ slots: << 2 << (QList() << QString() << "1.0.3" << 3); } - */ -/* void tst_UpdateChecking() { + ResetSetting resetUpdateChannel(MMC->settings()->getSetting("UpdateChannel")); + QFETCH(QString, channel); QFETCH(QString, channelUrl); QFETCH(int, currentBuild); QFETCH(QList, result); + MMC->settings()->set("UpdateChannel", channel); MMC->m_version.build = currentBuild; UpdateChecker checker; - checker.setCurrentChannel(channel); checker.setChannelListUrl(channelUrl); QSignalSpy updateAvailableSpy(&checker, SIGNAL(updateAvailable(QString,QString,int))); @@ -158,7 +176,6 @@ slots: res[0] = checker.m_channels[0].url; QCOMPARE(updateAvailableSpy.first(), res); } - */ }; QTEST_GUILESS_MAIN_MULTIMC(UpdateCheckerTest) diff --git a/translations/mmc_de.ts b/translations/mmc_de.ts index 42047378..7bca2272 100644 --- a/translations/mmc_de.ts +++ b/translations/mmc_de.ts @@ -1,51 +1,95 @@ - + AboutDialog - Dialog - Dialog + Dialog - + MultiMC MultiMC - + About Über - MultiMC is a custom launcher that makes managing Minecraft easier by allowing you to have multiple installations of Minecraft at once. - MultiMC ist ein alternativer Launcher, der das Management von Minecraft vereinfacht, indem er es dir erlaubt, mehrere Installationen von Minecraft zu verwalten. + MultiMC ist ein alternativer Launcher, der das Management von Minecraft vereinfacht, indem er es dir erlaubt, mehrere Installationen von Minecraft zu verwalten. - + + About MultiMC + Über MultiMC + + + + <html><head/><body><p>MultiMC is a custom launcher that makes managing Minecraft easier by allowing you to have multiple instances of Minecraft at once.</p></body></html> + <html><head/><body><p>MultiMC ist ein alternativer Launcher, der das Management von Minecraft vereinfacht, indem er es dir erlaubt, mehrere Installationen von Minecraft zu verwalten.</p></body></html> + + + © 2013 MultiMC Contributors - © 2013 MultiMC Contributors + © 2013 MultiMC-Mitwirkende - + <html><head/><body><p><a href="http://github.com/Forkk/MultiMC5"><span style=" text-decoration: underline; color:#0000ff;">http://github.com/MultiMC/MultiMC5</span></a></p></body></html> - - No Language file loaded. - Hey, Translator, You are free to put a reference to you here :) - Deutsche Sprachdatei von Kilobyte (siehe oben). - - - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:9pt; font-weight:400; font-style:normal;"> -<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 2012 MultiMC Contributors</span></p> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +<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; 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-size:10pt;">Andrew Okin &lt;</span><a href="mailto:forkk@forkk.net"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">forkk@forkk.net</span></a><span style=" font-size:10pt;">&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;">Petr Mrázek &lt;</span><a href="mailto:peterix@gmail.com"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">peterix@gmail.com</span></a><span style=" font-size:10pt;">&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;">Sky &lt;</span><a href="https://www.twitter.com/drayshak"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">@drayshak</span></a><span style=" font-size:10pt;">&gt;</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; font-weight:600;"><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; font-weight:600;">With thanks 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;">Orochimarufan &lt;</span><a href="mailto:orochimarufan.x3@gmail.com"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">orochimarufan.x3@gmail.com</span></a><span style=" font-size:10pt;">&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;">TakSuyu &lt;</span><a href="mailto:taksuyu@gmail.com"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">taksuyu@gmail.com</span></a><span style=" font-size:10pt;">&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;">Kilobyte &lt;</span><a href="mailto:stiepen22@gmx.de"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">stiepen22@gmx.de</span></a><span style=" font-size:10pt;">&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;">Jan (02JanDal) &lt;</span><a href="mailto:02jandal@gmail.com"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">02jandal@gmail.com</span></a><span style=" font-size:10pt;">&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;">Robotbrain &lt;</span><a href="https://twitter.com/skylordelros"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">@skylordelros</span></a><span style=" font-size:10pt;">&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;">Rootbear75 &lt;</span><a href="https://twitter.com/rootbear75"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">@rootbear75</span></a><span style=" font-size:10pt;">&gt; (build server)</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +<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; 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-size:10pt;">Andrew Okin &lt;</span><a href="mailto:forkk@forkk.net"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">forkk@forkk.net</span></a><span style=" font-size:10pt;">&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;">Petr Mrázek &lt;</span><a href="mailto:peterix@gmail.com"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">peterix@gmail.com</span></a><span style=" font-size:10pt;">&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;">Sky &lt;</span><a href="https://www.twitter.com/drayshak"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">@drayshak</span></a><span style=" font-size:10pt;">&gt;</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; font-weight:600;"><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; font-weight:600;">Mit dank 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;">Orochimarufan &lt;</span><a href="mailto:orochimarufan.x3@gmail.com"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">orochimarufan.x3@gmail.com</span></a><span style=" font-size:10pt;">&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;">TakSuyu &lt;</span><a href="mailto:taksuyu@gmail.com"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">taksuyu@gmail.com</span></a><span style=" font-size:10pt;">&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;">Kilobyte &lt;</span><a href="mailto:stiepen22@gmx.de"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">stiepen22@gmx.de</span></a><span style=" font-size:10pt;">&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;">Jan (02JanDal) &lt;</span><a href="mailto:02jandal@gmail.com"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">02jandal@gmail.com</span></a><span style=" font-size:10pt;">&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;">Robotbrain &lt;</span><a href="https://twitter.com/skylordelros"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">@skylordelros</span></a><span style=" font-size:10pt;">&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;">Rootbear75 &lt;</span><a href="https://twitter.com/rootbear75"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">@rootbear75</span></a><span style=" font-size:10pt;">&gt; (bau server)</span></p></body></html> + + + + No Language file loaded. + Hey, Translator, feel free to put credit to you here + Deutsche Sprachdatei von Kilobyte (siehe oben). Aktualisiert von xnrand (nsfw auf IRC), Jan und ACGaming. + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans Mono'; font-size:7.8pt; 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-family:'Bitstream Vera Sans'; 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-size:10pt;">Copyright 2012-2014 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-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-size:10pt;">you may not use this file except in compliance with the 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;">You may obtain a copy of the License at</span></p> @@ -58,39 +102,271 @@ 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-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-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-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;">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-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 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-family:'Bitstream Vera Sans'; 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:8pt;">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:8pt;">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:8pt;"><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:8pt;">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:8pt;">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:8pt;"><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:8pt;">* 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:8pt;"> 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:8pt;">* 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:8pt;"> 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:8pt;"> 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:8pt;">* 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:8pt;"> 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:8pt;"><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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;"><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-family:'Bitstream Vera Sans'; 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:8pt;"> /*</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:8pt;"> * 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:8pt;"> * 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:8pt;"> *</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:8pt;"> * 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:8pt;"> * 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:8pt;"> * 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:8pt;"> * 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:8pt;"> *</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:8pt;"> * 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:8pt;"> * 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:8pt;"> * 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:8pt;"> * 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:8pt;"> *</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:8pt;"> * 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:8pt;"> * 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:8pt;"> * 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:8pt;"> * 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:8pt;"> */</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:8pt;"><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-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">Pack200</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:8pt;">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:8pt;"><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:8pt;">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:8pt;"><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:8pt;">+ &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:8pt;"><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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;"><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:8pt;"> 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:8pt;"> 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:8pt;"> 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:8pt;"><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:8pt;"> 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:8pt;"> 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:8pt;"> 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:8pt;"> 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:8pt;"> 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:8pt;"> 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:8pt;"> 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:8pt;"> 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:8pt;"> 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:8pt;"> 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:8pt;"><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-family:'Bitstream Vera Sans'; 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:8pt;">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:8pt;"><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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;"><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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;"><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:8pt;">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:8pt;">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:8pt;">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:8pt;"><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:8pt;">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:8pt;"><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:8pt;">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:8pt;">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; font-size:8pt;"><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-family:'Bitstream Vera Sans'; 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:8pt;">/*</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:8pt;"> * 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:8pt;"> *</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:8pt;"> * 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:8pt;"> * 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:8pt;"> *</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:8pt;"> * 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:8pt;"> * 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:8pt;"> */</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans Mono'; font-size:7.8pt; 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-family:'Bitstream Vera Sans'; 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-size:10pt;">Copyright 2012-2014 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-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-size:10pt;">you may not use this file except in compliance with the 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;">You may obtain a copy of the License at</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=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> http://www.apache.org/licenses/LICENSE-2.0</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=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Unless required by applicable law or agreed to in writing, software</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;">distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</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 WARRANTIES OR CONDITIONS OF ANY KIND, either express or 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;">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-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-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></body></html> - +<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-family:'Bitstream Vera Sans'; 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:8pt;">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:8pt;">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:8pt;"><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:8pt;">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:8pt;">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:8pt;"><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:8pt;">* 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:8pt;"> 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:8pt;">* 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:8pt;"> 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:8pt;"> 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:8pt;">* 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:8pt;"> 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:8pt;"><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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;"><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-family:'Bitstream Vera Sans'; 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:8pt;"> /*</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:8pt;"> * 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:8pt;"> * 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:8pt;"> *</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:8pt;"> * 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:8pt;"> * 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:8pt;"> * 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:8pt;"> * 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:8pt;"> *</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:8pt;"> * 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:8pt;"> * 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:8pt;"> * 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:8pt;"> * 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:8pt;"> *</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:8pt;"> * 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:8pt;"> * 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:8pt;"> * 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:8pt;"> * 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:8pt;"> */</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:8pt;"><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-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">Pack200</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:8pt;">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:8pt;"><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:8pt;">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:8pt;"><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:8pt;">+ &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:8pt;"><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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;"><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:8pt;"> 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:8pt;"> 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:8pt;"> 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:8pt;"><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:8pt;"> 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:8pt;"> 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:8pt;"> 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:8pt;"> 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:8pt;"> 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:8pt;"> 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:8pt;"> 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:8pt;"> 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:8pt;"> 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:8pt;"> 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:8pt;"><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-family:'Bitstream Vera Sans'; 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:8pt;">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:8pt;"><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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;"><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:8pt;">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:8pt;">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:8pt;">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:8pt;">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:8pt;"><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:8pt;">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:8pt;">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:8pt;">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:8pt;"><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:8pt;">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:8pt;"><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:8pt;">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:8pt;">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; font-size:8pt;"><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-family:'Bitstream Vera Sans'; 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:8pt;">/*</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:8pt;"> * 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:8pt;"> *</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:8pt;"> * 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:8pt;"> * 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:8pt;"> *</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:8pt;"> * 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:8pt;"> * 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:8pt;"> */</span></p></body></html> + + + + Forking/Redistribution + Abspaltung/Weiterverbreitung + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +<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:'Bitstream Vera Sans'; font-size:11pt;">We keep MultiMC open source because we think it's important to be able to see the source code for a project like this, and we do so using the Apache 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:'Bitstream Vera Sans'; font-size:11pt;"><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:'Bitstream Vera Sans'; font-size:11pt;">Part of the reason for using the Apache license is we don't want people using the &quot;MultiMC&quot; name when redistributing the project. This means people must take the time to go through the source code and remove all references to &quot;MultiMC&quot;, including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).</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:'Bitstream Vera Sans'; font-size:11pt;"><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:'Bitstream Vera Sans'; font-size:11pt;">The Apache license covers reasonable use for the name - a mention of the project's origins in the About dialog and the license is acceptable. However, it should be abundantly clear that the project is a fork </span><span style=" font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:600;">without</span><span style=" font-family:'Bitstream Vera Sans'; font-size:11pt;"> implying that you have our blessing.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +<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:'Bitstream Vera Sans'; font-size:11pt;">Wir wollen, dass MultiMC Open Source bleibt, da wir glauben, dass es wichtig ist, den Quellcode von einem Projekt wie diesem, einzusehen. Daher verbreiten wir MultiMC unter der Apache-Lizenz</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:'Bitstream Vera Sans'; font-size:11pt;"><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:'Bitstream Vera Sans'; font-size:11pt;">Eine der Gründe, warum wir die Apache-Lizenz gewählt haben, ist, dass wir nicht wollen, dass der &quot;MultiMC&quot;-Name beim Weiterverbreiten benutzt wird. Dies bedeutet, dass Leute sich die Zeit nehmen müssen, den Code durchzugehen und alle Referenzen zu &quot;MultiMC&quot;, miteinbegriffen aber nicht begrenzt zu dem &quot;MultiMC&quot;-Logo und den Fenstertiteln (kein *MultiMC-fork* im Titel)</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:'Bitstream Vera Sans'; font-size:11pt;"><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:'Bitstream Vera Sans'; font-size:11pt;">Die Apache-Lizenz gibt Ihnen ein angemessenes Recht, den Namen zu benutzen - eine Bemerkung im Über-Dialog und in der Lizenz ist akzeptabel. Es sollte allerdings klar sein, dass das Projekt eine Abspaltung </span><span style=" font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:600;">ohne</span><span style=" font-family:'Bitstream Vera Sans'; font-size:11pt;"> unserem Segen ist</span></p></body></html> <html><head/><body><p><a href="http://github.com/Forkk/MultiMC5"><span style=" text-decoration: underline; color:#0000ff;">http://github.com/Forkk/MultiMC5</span></a></p></body></html> <html><head/><body><p><a href="http://github.com/Forkk/MultiMC5"><span style=" text-decoration: underline; color:#0000ff;">http://github.com/Forkk/MultiMC5</span></a></p></body></html> - + Credits Dank an @@ -112,7 +388,7 @@ 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;">Deutsche Übersetzung: Kilobyte &lt;<a href="mailto:stiepen22@gmx.de"><span style=" text-decoration: underline; color:#0000ff;">stiepen22@gmx.de</span></a>&gt;</p></body></html> - + License Lizenz @@ -201,83 +477,289 @@ 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-size:10pt;">POSSIBILITY OF SUCH DAMAGE.</span></p></body></html> - + About Qt Über Qt - + Close Schließen + + AccountListDialog + + + Manage Accounts + Kontoverwaltung + + + + <html><head/><body><p>Welcome! If you're new here, you can click the &quot;Add&quot; button to add your Mojang or Minecraft account.</p></body></html> + <html><head/><body><p>Willkommen! Solltest du neu sein, kannst du die &quot;Hinzufügen&quot;-Schaltfläche drucken um dein Mojang- oder Minecraft-Konto hinzuzufügen</p></body></html> + + + + &Add + &Hinzufügen + + + + &Remove + &Entfernen + + + + <html><head/><body><p>Set the currently selected account as the active account. The active account is the account that is used to log in (unless it is overridden in an instance-specific setting).</p></body></html> + <html><head/><body><p>Mache das ausgewählten Konto zum voreingestellten Konto. Das voreingestellte Konto ist das Konto das zum Einloggen benutzt wird (es sei denn es wird von einer Instanz-spezifischen Einstellung überschrieben).</p></body></html> + + + + &Set Default + &Benutze als Voreinstellung + + + + Set no default account. This will cause MultiMC to prompt you to select an account every time you launch an instance that doesn't have its own default set. + Mache die Voreinstellung rückgängig. Wenn kein Konto voreingestellt ist, wird MultiMC dich bei jedem Start einer Instanz fragen, welches Konto benutzt werden soll, es sei denn, die Instanz hat ein instanzspezifisches Konto eingestellt. + + + + &No Default + &Keine Voreinstellung + + + + Please enter your Mojang or Minecraft account username and password to add your account. + Bitte gib Benutzernamen und Passwort deines Mojang- oder Minecraft-Kontos an, um es hinzuzufügen. + + + + Login error. + Loginfehler. + + + + AccountSelectDialog + + + Select an Account + Wähle ein Konto + + + + Select an account. + Wähle ein Konto. + + + + Use as default? + Als Voreinstellung benutzen? + + + + Use as default for this instance only? + Nur für diese Instanz als Voreinstellung benutzen? + + + + AssetsMigrateTask + + + Migrating legacy assets... + Migriere bestehende Daten... + + + + AuthenticateTask + + + Authenticating: Sending request... + Authentifizierung: Sende Anfrage... + + + + Authenticating: Processing response... + Authentifizierung: Bearbeite Antwort... + + ConsoleWindow - + MultiMC Console MultiMC-Konsole - + + Upload Log + Log hochladen + + + + &Kill Minecraft + &Minecraft töten + + + + &Close + &Schließen + + Kill Minecraft - Minecraft Killen + Minecraft töten - Close - Schließen + Schließen - + Kill Minecraft? - Main question of the kill confirmation dialog - Minecraft Killen? + Minecraft töten? - + This can cause the instance to get corrupted and should only be used if Minecraft is frozen for some reason Dies kann diese Instanz beschädigen und sollte daher nur genutzt werden, wenn Minecraft eingefroren ist + + CopyInstanceDialog + + + Copy Instance + Kopiere Instanz + + + + Name + Name + + + + DownloadUpdateTask + + + Finding information about the current version... + Finde Informationen zur benutzten Version... + + + + Loading version information... + Lade Versionsinformationen... + + + + Failed to download version info files. + Laden der Versionsdateien ist fehlgeschlagen. + + + + Reading file list for new version... + Bearbeite die Dateiliste der neuen Version... + + + + Reading file list for current version... + Bearbeite die Dateiliste der benutzten Version... + + + + Failed to process update lists... + Fehler beim Bearbeiten der Updateliste... + + + + Downloading %1 update files. + %1 Dateien werden heruntergeladen. + + + + Processing file lists - figuring out how to install the update... + Bearbeite Dateilisten - Rechne aus, wie das Update installiert werden soll... + + + + Failed to write update script file. + Fehler beim Schreiben des Updatescripts. + + + + Failed to download update files. + Fehler beim Herunterladen der Updatedateien. + + + + EditAccountDialog + + + Edit Account + Bearbeite Konto + + + + Message label placeholder. + Message label placeholder. + + + + Email / Username + E-Mail / Benutzername + + + + Password + Passwort + + EditNotesDialog - + Edit Notes Notizen bearbeiten - + Edit notes of %1 Notizen von %1 bearbeiten + + ForgeListLoadTask + + + Fetching Forge version lists... + Lade die Forge-Versionslisten... + + IconPickerDialog - + Pick icon Symbol auswählen - + Add Icon Symbol hinzufügen - + Remove Icon Symbol entfernen - + Select Icons The title of the select icons open file dialog Symbol auswählen - + Icons The type of icon files Symbole @@ -286,140 +768,190 @@ p, li { white-space: pre-wrap; } InstanceSettings - + + Instance Settings + Instanzeinstellungen + + + Minecraft - + Window Size Fenstergröße - + Start Minecraft maximized? Minecraft maximiert starten? - + Window height: Fensterhöhe: - + Window width: Fensterbreite: - + Console Settings Konsoleneinstellungen - + Show console while the game is running? - Konsole anzeigen wenn das Spiel läuft? + Konsole anzeigen, während das Spiel läuft? - + Automatically close console when the game quits? Konsole automatisch schließen, nachdem das Spiel beendet wurde? - + + Browse... + Durchsuchen... + + + + Auto-detect... + Auto-Erkennung... + + Account Settings - Konteneinstellungen + Konteneinstellungen - Login automatically when an instance icon is double clicked? - Automatisch einloggen, wenn das Instanzsymbol doppelt gecklickt wurde? + Automatisch einloggen, wenn das Instanzsymbol doppelt gecklickt wurde? - + Java Java - + Memory Arbeitsspeicher - + Minimum memory allocation: - Min. Arbeitspeicher: + Min. Arbeitsspeicher: - + Maximum memory allocation: - Max. Arbeitspeicher: + Max. Arbeitsspeicher: - + PermGen: PermGen: - + Java Settings Java-Einstellungen - + + Test + Teste + + + Java path: Java-Pfad: - + JVM arguments: JVM-Argumente: - Auto-detect - Automatisch erkennen + Automatisch erkennen - + Custom Commands Eigene Befehle - + Post-exit command: - Nach-abschluss-Befehl: + Nach-Abschluss-Befehl: - + Pre-launch command: Vor-Start-Befehl: - + Pre-launch command runs before the instance launches and post-exit command runs after it exits. Both will be run in MultiMC's working directory with INST_ID, INST_DIR, and INST_NAME as environment variables. - Vor-Start wird ausgeführt, bevor die Instanz startet, Nach-Ende nachdem die Instanz beendet wurde. Beide werden Im ausführungsverzeichnis von MultiMC gestartet. Verfügbare Umgebungsvariablen: INST_ID, INST_DIR, INST_NAME. + Vor-Start-Befehle werden ausgeführt, bevor die Instanz startet, Nach-Ende-Befehle nachdem die Instanz beendet wurde. Beide werden im Hauptverzeichnis von MultiMC gestartet. Verfügbare Umgebungsvariablen: INST_ID, INST_DIR, INST_NAME. + + + + Select a Java version + Wähle eine Java-Version + + + + Find Java executable + Java-Programm finden + + + + Java test success + Java-Test erfolgreich abgeschlossen + + + + Java test failure + Java-Test fehlgeschlagen + + + + The specified java binary didn't work. You should use the auto-detect feature, or set the path to the java executable. + Das ausgewählte Java-Programm hat nicht funktioniert. Du solltest die Auto-Erkennung benutzen, oder den Pfad zum Java-Programm angeben. + + + + JavaListLoadTask + + + Detecting Java installations... + Suche nach Java-Installationen... LWJGLSelectDialog - - Dialog - + + Manage Lwjgl Versions + LWJGL-Versionsverwaltung - + Status label... - + &Refresh - Anktualisie&ren + &Aktualisieren - + Loading LWJGL version list... Lade LWJGL-Versionsliste... @@ -427,550 +959,788 @@ p, li { white-space: pre-wrap; } LegacyModEditDialog - - Dialog - + + Edit Mods + Mods bearbeiten - + Jar Mods Jar-Mods - - - - + + + + &Add &Hinzufügen - - - - + + + + &Remove &Entfernen - + MCForge - + Move &Up - &Nach Oben + Bewege &nach oben - + Move &Down - Nach &Unten + Bewege &nach unten - + Core Mods Coremods - - - + + + &View Folder &Ordner öffnen - + Loader Mods Normale Mods - + Texture Packs - Texturenpacks + Texturenpakete - - + + Select Loader Mods Title of regular mod selection dialog Mods auswählen - + Select Resource Packs - Resourcenpacks auswählen + Ressourcenpakete auswählen - + Select Core Mods Title of core mod selection dialog - Coremodsauswählen + Coremods auswählen - + + Select Forge version + Wähle Forge-Version + + + Select Jar Mods Title of jar mod selection dialog Jarmods auswählen - + Select Texture Packs Title of texture pack selection dialog - Texturenpacks auswählen + Texturenpakete auswählen + + + + LegacyUpdate + + + Downloading new LWJGL... + LWJGL wird heruntergeladen... + + + + Installing new LWJGL... + Neues LWJGL wird installiert... + + + + Installing new LWJGL - extracting + Das neue LWJGL wird installiert - entpacken + + + + Checking for jar updates... + Suche nach Jar-Änderungen... + + + + Downloading new minecraft.jar ... + Neue minecraft.jar wird heruntergeladen... + + + + Installing mods: Adding + Mod-Installation: Hinzufügen + + + + Installing mods: Backing up minecraft.jar ... + Mod-Installation: Erstellen einer Sicherheitskopie von minecraft.jar... + + + + Installing mods: Opening minecraft.jar ... + Mod-Installation: minecraft.jar wird geöffnet... + + + + Installing mods: Adding mod files... + Mod-Installation: Mod-Dateien werden hinzugefügt... LoginDialog - Login - Einloggen + Einloggen - - <span style=" color:#ff0000;">Error</span> - - - - Username: - Nutzername: + Nutzername: - Password: - Passwort: + Passwort: - Password - Passwort + Passwort - Forget - Vergessen + Vergessen - &Remember Username? - &Nutzernamen speichern? + &Nutzernamen speichern? - R&emember Password? - &Passwort speichern? + &Passwort speichern? - Offline Once Use offline mode one time - Einmal Offline + Einmal Offline-Modus verwenden - Name The username during login (placeholder) - Name + Name LoginTask - - Logging in... - Einloggen... + Einloggen... Failed to parse Minecraft version string. Konnte Minecraft-Versionsstring nicht parsen. - Invalid username or password. - Falsche Kombination von Nutzernamen und Passwort. + Falscher Nutzername oder Passwort. - Launcher outdated, please update. - Veralteter Launcher, Bitte lade ein Update herunter. + Veralteter Launcher, bitte lade ein Update herunter. - - - - Login failed: %1 - Login fehlgeschlagen: %1 + Login fehlgeschlagen: %1 - - The login servers are currently unavailable. Check http://help.mojang.com/ for more info. - Derzeit kann auf die Login-Server nicht zugegriffe werden. Für weitere Informationen siehe http://help.mojang.com/. + Derzeit kann auf die Login-Server nicht zugegriffen werden. Für weitere Informationen siehe http://help.mojang.com/. - - Login failed: Unknown HTTP error %1 occurred. - Login fehlgeschlagen. Unbekannter HTTP-Fehler: %1. + Login fehlgeschlagen. Unbekannter HTTP-Fehler: %1. - - Login canceled. - Login abgebrochen. + Login abgebrochen. + + + + MCModInfoFrame + + + Frame + Frame - - Login failed: BAD FORMAT #1 - Login fehlgeschlagen: UNGÜLTIGES FORMAT #1 - + + + Select a mod to view title and authors... + Wähle eine Modifikation aus, um Titel und Autor(en) zu sehen... + + + + + Select a mod to view description... + Wähle eine Modifikation aus, um die Beschreibung zu sehen... + + + + No description provided in mcmod.info + mcmod.info wurde mit keiner Beschreibung versehen + + + + MCVListLoadTask + + + Loading instance version list... + Lade Liste von Minecraft-Versionen... MainWindow - + MultiMC 5 MultiMC 5 - + Main Toolbar Haupt-Werkzeugleiste - + Instance Toolbar Instanz-Werkzeugleiste - + + News Toolbar + Nachrichten-Werkzeugleiste + + + Add Instance Instanz hinzufügen - - + + + Add a new instance. Neue Instanz erstellen. - + View Instance Folder Instanzordner öffnen - - + + Open the instance folder in a file browser. Instanzordner im Dateimanager öffnen. - + Refresh Aktualisieren - - + + Reload the instance list. - Instanzliste neu Laden. + Instanzliste neuladen. - + View Central Mods Folder - Zenstralen Modordner öffnen + Zenstralen Mod-Ordner öffnen - - + + Open the central mods folder in a file browser. - Zentralen Modordner in einem Dateimanager öffnen. + Zentralen Mod-Ordner in einem Dateimanager öffnen. - + Check for Updates Auf Updates überprüfen - - + + Check for new updates for MultiMC Auf Updates für MultiMC prüfen - - + + Settings Einstellungen - - + + Change settings. Einstellungen ändern. - + Report a Bug Fehler melden - - + + Open the bug tracker to report a bug with MultiMC. - Fehler-Verfolgung öffnen, um einen Fehler zu melden (Bitte auf Englisch ;)) + Fehler-Verfolgung öffnen, um einen Fehler zu melden (Bitte auf Englisch ;)). - News - Neuigkeiten + Neuigkeiten - - Open the MultiMC dev blog to read news about MultiMC. - Den MultiMC Entwicklerblog öffnen und Neuigkeiten über MultiMC erfahren. + Den MultiMC-Entwicklerblog öffnen, um Neuigkeiten über MultiMC zu erhalten. - - + + More News + Mehr Nachrichten + + + + More news... + Mehr Nachrichten... + + + + + Open the MultiMC development blog to read more news about MultiMC. + Öffne den MultiMC-Entwicklerblog, um weitere Neuigkeiten über MultiMC zu erhalten. + + + + About MultiMC Über MultiMC - + View information about MultiMC. Informationen über MultiMC anzeigen. - + Play Spielen - - + + Launch the selected instance. Die ausgewählte Instanz starten. - + Instance Name Instanzname - - + + Rename the selected instance. Ausgewählte Instanz umbenennen. - + Change Group Gruppe ändern - - + + Change the selected instance's group. Die Gruppe der ausgewählten Instanz ändern. - + Change Icon Symbol ändern - - + + Change the selected instance's icon. Das Symbol der ausgewählten Instanz ändern. - + Edit Notes Notizen bearbeiten - - + + Edit the notes for the selected instance. Notizen für die ausgewählte Instanz bearbeiten. - - + + Change settings for the selected instance. Einstellungen für die ausgewählte Instanz bearbeiten. - + Make Shortcut Verknüpfung erstellen - - + + Make a shortcut on the desktop for the selected instance. Erstellt eine Verknüpfung für die ausgewählte Instanz auf dem Desktop. - + Manage Saves Speicherstände verwalten - - + + Manage saves for the selected instance. Die Speicherstände der ausgewählten Instanz verwalten. - + Edit Mods Mods bearbeiten - - + + Edit the mods for the selected instance. Die Mods der ausgewähten Instanz bearbeiten. - + Change Version Version ändern - - + + Change the selected instance's Minecraft version. Die Minecraftversion der ausgewählten Instanz ändern. - + Change LWJGL LWJGL ändern - - + + Change the version of LWJGL for the selected instance to use. Die zu benutzende Version von LWJGL für die aktuelle Instanz ändern. - + Instance Folder Instanzordner - - + + Open the selected instance's root folder in a file browser. - Den Wurzelordner der Aktuellen Instanz im Dateimanager öffnen. + Das Hauptverzeichnis der aktuellen Instanz im Dateimanager öffnen. - + Delete Löschen - - + + Delete the selected instance. Ausgewählte Instanz löschen. - + Config Folder - Konfig-ordner + Konfig-Ordner - + Open the instance's config folder Den Konfigurationsordner im Dateimanager anzeigen - + Meow Miau - + <html><head/><body><p align="center"><span style=" font-weight:600; color:#ff0004;">Catnarok!</span></p><p align="center">Or just a cat with a ball of yarn?</p><p align="center"><span style=" font-style:italic;">WHO KNOWS?!</span></p><p align="center"><img src=":/icons/instances/tnt"/></p></body></html> + + + Copy Instance + Kopiere Instanz + + + + Copy the selected instance. + Kopiere die ausgewählte Instanz. + + + + + Manage Accounts + Verwalte Konten + + + + Manage your Mojang or Minecraft accounts. + Verwalte deine Mojang- und Minecraft-Konten. + <html><head/><body><p align="center"><span style=" font-weight:600; color:#ff0004;">Catnatok!</span></p><p align="center">Or just a cat with a ball of yarn?</p><p align="center"><span style=" font-style:italic;">WHO KNOWS?!</span></p><p align="center"><img src=":/icons/instances/tnt"/></p></body></html> <html><head/><body><p align="center"><span style=" font-weight:600; color:#ff0004;">Catnatok!</span></p><p align="center">Or just a cat with a ball of yarn?</p><p align="center"><span style=" font-style:italic;">WHO KNOWS?!</span></p><p align="center"><img src=":/icons/instances/tnt"/></p></body></html> - + + No instance selected + Keine Instanz ausgewählt + + + + Accounts + Konten + + + + No update found. + Keine neue Version gefunden. + + + + No MultiMC update was found! +You are using the latest version. + Es wurde kein Update für MultiMC gefunden! +Du verwendest bereits die neueste Version. + + + + No accounts added! + Keine Konten angegeben! + + + + No Default Account + Kein voreingestelltes Konto + + + + Loading news... + Nachrichten werden geladen... + + + + No news available. + Keine Nachrichten verfügbar. + + + + + + + + + + + + Error + Fehler + + + + + MultiMC cannot download Minecraft or update instances unless you have at least one account added. +Please add your Mojang or Minecraft account. + MultiMC kann Minecraft nicht herunterladen und keine Instanzen aktualisieren, solange du kein Konto erstellt hast. +Bitte füge dein Mojang- oder Minecraft-Konto hinzu. + + + Group name Gruppenname - + Enter a new group name. Neuen Gruppennamen eingeben. - + + CAREFUL + ACHTUNG + + + + This is permanent! Are you sure? +About to delete: + Die Änderung ist dauerhaft! Bist du dir sicher? +Die folgende Instanz löschen: + + + Instance name Instanzname - + Enter a new instance name. Neuen Instanznamen eingeben. - + + No Accounts + Keine Konten + + + + In order to play Minecraft, you must have at least one Mojang or Minecraft account logged in to MultiMC.Would you like to open the account manager to add an account now? + Um Minecraft spielen zu können, musst du mindestens ein Mojang- oder Minecraft-Konto in MultiMC hinterlegen. Möchtest du die Kontoverwaltung öffnen, um ein Konto hinzuzufügen? + + + + Which account would you like to use? + Welches Konto möchtest du benutzen? + + + + Your account is currently not logged in. Please enter your password to log in again. + Dein Konto ist momentan nicht angemeldet. Bitte gib dein Passwort an, um dich anzumelden. + + + + Play Offline + Offline spielen + + + + Error updating instance + Fehler beim Aktualisieren der Instanz + + + MultiMC Shortcut MultiMC-Verknüpfung - + Enter a Shortcut Name. Verknüpfungsnamen eingeben. - + Not useful Sinnlos - + A Dummy Shortcut was created. it will not do anything productive Eine Dummy-Verknüpfung wurde erstellt. Sie wird jedoch absolut nichts bewirken - + + Change Minecraft version + Minecraft-Version ändern + + + + Are you sure? + Bist du sicher? + + + + This will remove any library/version customization you did previously. This includes things like Forge install and similar. + Dies wird sämtliche Bibliotheken-/Versions-Anpassungen, die du vorgenommen hast, entfernen. Dies schließt Dinge wie Forge mit ein. + + + + Instance settings + Instanzeinstellungen + + + Rename Instance Instanz umbenennen + + + Select a Java version + Wähle eine Java-Version + + + + Invalid version selected + Ungültige Version ausgewählt + + + + You didn't select a valid Java version, so MultiMC will select the default. You can change this in the settings dialog. + Du hast keine gültige Java-Version ausgewählt, daher wird MultiMC die Voreinstellung benutzen. Du kannst dies in den Einstellungen ändern. + MinecraftProcess - + Minecraft exited with exitcode %1. Message displayed on instance exit - Minecraft wurde mit exitcode %1 beendet. + Minecraft wurde mit Status %1 beendet. - + + Minecraft crashed with exitcode %1. + Message displayed on instance crashed + Minecraft ist mit dem Status %1 abgestürzt + + + Minecraft was killed by user. Message displayed after the instance exits due to kill request - Minecraft wurde durch den nutzer gekillt. + Minecraft wurde durch den Nutzer getötet. - + Could not launch minecraft! Error message displayed if instace can't start Konnte Minecraft nicht starten! @@ -980,15 +1750,15 @@ p, li { white-space: pre-wrap; } MultiMC display this help and exit. - Zeigt diese Hilfe und beended das Programm. + Zeigt diese Hilfe und beendet das Programm. display program version and exit. - Zeigt die programmversion an und beendet das Programm. + Zeigt die Programmversion an und beendet das Programm. use the supplied directory as MultiMC root instead of the binary location (use '.' for current) - Benutze das angegebene Verzeichnis als Arbeitsverzeichnis anstelle des speicherorts. (Benutze '.' um das aktuele Verzeichnis zu verwenden) + Benutze das angegebene Verzeichnis als Hauptverzeichnis anstelle des Speicherorts. (Benutze '.', um das aktuelle Verzeichnis zu verwenden) replaces the given file with the running executable @@ -996,27 +1766,27 @@ p, li { white-space: pre-wrap; } <path> - <pfad> + <Pfad> doesn't restart MultiMC after installing updates - MultiMC nach dem Update nicht neu starten + MultiMC nach dem Update nicht neustarten tries to launch the given instance - Versucht die angegebene Instanz zu starten + Versucht, die angegebene Instanz zu starten <inst> - <instanz> + <Instanz> CommandLineError: - KommandoZeilenFehler: + Kommandozeilenfehler: Try '%1 -h' to get help on MultiMC's command line parameters. - Versuche '%1 -h' um Hilfe zu MultiMCs Kommandozeilenparametern zu bekommen. + Versuche '%1 -h', um Hilfe zu MultiMCs Kommandozeilenparametern zu bekommen. Performing MultiMC update: @@ -1030,362 +1800,632 @@ p, li { white-space: pre-wrap; } NewInstanceDialog - + New Instance Neue Instanz - + Name Name - + Version: Version: - + ... ... + + + Change Minecraft version + Ändere die Minecraft-Version... + + + + NewsEntry + + + + Untitled + Unbennant + + + + + No content. + Kein Eintrag. + + + + + Unknown Author + Unbekannter Autor + + + + OneSixFTBInstanceForge + + + Downloading Forge... + Forge wird heruntergeladen... + + + + Installing Forge... + Forge wird installiert... + + + + Couldn't load the version config + Fehlschlag beim Laden der Versions-Konfiguration + + + + Couldn't install Forge + Fehler beim Installieren von Forge + OneSixModEditDialog - Dialog Am i really responsible for this? - Edit Mods + Edit Mods Library Bibliothek - + Loader Mods Mods - - - + + + &Add &Hinzufügen - + + Manage Mods + Verwalte Mods + + + Version Version - + Main Class: Hauptklasse: - + Replace any current custom version with Minecraft Forge Die aktuelle benutzerdefinierte Version mit Minecraft Forge ersetzen - + Install Forge - Forge Installieren + Forge installieren - + + Install LiteLoader + Installiere LiteLoader + + + Create an customized copy of the base version - Eine modifizierbare Kopie der Version erstellen + Eine modifizierte Kopie der Version erstellen - + Customize Benutzerdefiniert - + Revert to original base version Benutzerdefinierte Einstellungen zurücksetzen - + Revert Zurücksetzen - + Add new libraries - + Füge neue Bibliotheken hinzu - + Remove selected libraries - + Entferne ausgewählte Bibliotheken - - - + + + &Remove &Entfernen - - + + Open custom.json + Öffne custom.json + + + + &View Folder &Ordner öffnen - + Resource Packs - Resourcenpacks + Ressourcenpakete - - + + Revert? Zurücksetzen? - + Do you want to revert the version of this instance to its original configuration? Möchtest du wirklich die Version dieser Instanz zurücksetzen? - + + Error + Fehler + + + + Unable to open custom.json, check the settings + Fehler beim Öffnen der custom.json-Datei, überprüfe deine Einstellungen + + + + Select Forge version + Wähle Forge-Version + + + This will revert any changes you did to the version up to this point. Is that OK? - Dies wird alle Änderungen, die du vorgenommen hast zurücksetzen. Bist du damit einverstanden? + Dies wird alle Änderungen, die du vorgenommen hast, zurücksetzen. Bist du damit einverstanden? + + + + + LiteLoader + LiteLoader + + + + There is no information available on how to install LiteLoader into this version of Minecraft + Es gibt momentan keine Informationen zur Installation von LiteLoader für diese Version von Minecraft + + + + For reasons unknown, the LiteLoader installation failed. Check your MultiMC log files for details. + Aus unbekannten Gründen ist die Installation von LiteLoader fehlgeschlagen. Sieh dir die MultiMC-Logdateien an, um weitere Details zu erhalten. + + + + OneSixUpdate + + + + Testing the Java installation... + Java-Installation wird getestet... + + + + Getting the version files from Mojang... + Versionsdateien von Mojang werden heruntergeladen... + + + + Updating assets index... + Datenindex wird aktualisiert... + + + + Getting the assets files from Mojang... + Daten werden von Mojang geholt... + + + + Getting the library files from Mojang... + Bibliotheken werden von Mojang geholt... + + + + Preparing for launch... + Start wird vorbereitet... ProgressDialog - + Please wait... Bitte warten... - + Task Status... Aufgabenstatus... + + + Skip + Überspringen + + + + QObject + + + JVM arguments warning + JVM-Argument-Warnung + + + + You tried to manually set a JVM memory option (using "-XX:PermSize", "-Xmx" or "-Xms") - there are dedicated boxes for these in the settings (Java tab, in the Memory group at the top). +Your manual settings will be overridden by the dedicated options. +This message will be displayed until you remove them from the JVM arguments. + Du hast versucht, eine JVM-Arbeitsspeicheroption manuell anzugeben ("-XX:PermSize", "-Xmx" oder "-Xms") - es gibt hierfür vorgesehene Felder in den Einstellungen (Java-Reiter, im Arbeitsspeicher-Bereich oben). +Deine manuellen Einstellungen werden von den vorgesehenen überschrieben. +Diese Mitteilung wird so lange angezeigt, bis du die Option entfernt hast. + + + + How sad! + Wie schade! + + + + The mod author didn't provide a website link for this mod. + Der Autor der Modifikation hat keine URL hinterlegt. + + + + RefreshTask + + + Refreshing login token... + Erneuerung des Login-Tokens... + + + + Refreshing login token: Processing response... + Erneuerung des Login-Tokens: Verarbeite Antwort... + SettingsDialog - + Settings Einstellungen - + General - Generell + Allgemein - + Sorting Mode Sortiermodus - + By last launched Nach letzem Start - + By name Nach Namen - + Update Settings Updateeinstellungen - + Use development builds? - Entwicklerversionen benutzen? + Entwicklungsversionen benutzen? - + Check for updates when MultiMC starts? Beim Start nach Updates suchen? - + Folders Ordner - + Instances: Instanzen: - - - + + + + + + + + ... ... - + + FTB + FTB + + + + Launcher: + Launcher: + + + + Track FTB instances + FTB-Instanzen beobachten + + + + Files: + Dateien: + + + Mods: Mods: - + LWJGL: LWJGL: - + + Icons: + Symbole: + + + + External Editors (leave empty for system default) + Externe Editor-Anwendungen (leer lassen, um die System-Voreinstellung zu benutzen) + + + + JSON Editor: + JSON-Editor: + + + Minecraft Minecraft - + Window Size Fenstergröße - + Start Minecraft maximized? Minecraft maximiert starten? - + Window height: Fensterhöhe: - + Window width: Fensterbreite: - + Console Settings Konsoleneinstellungen - + Show console while the game is running? - Konsole anzeigen wenn das Spiel läuft? + Konsole anzeigen, während das Spiel läuft? - + Automatically close console when the game quits? Konsole automatisch schließen, nachdem das Spiel beendet wurde? - Login automatically when an instance icon is double clicked? - Automatisch einloggen, wenn das Instanzsymbol doppelt gecklickt wurde? + Automatisch einloggen, wenn das Instanzsymbol doppelt geklickt wurde? - + Java Java - + Memory Arbeitsspeicher - + Minimum memory allocation: Min. Arbeitspeicher: - + Maximum memory allocation: Max. Arbeitspeicher: - + PermGen: PermGen: - + Java Settings Java-Einstellungen - + Java path: Java-Pfad: - + + Auto-detect... + Auto-Erkennung: + + + + Test + Test + + + JVM arguments: JVM-Argumente: - Browse... - Durchsuchen... + Durchsuchen... - Auto-detect - Automatisch erkennen + Automatisch erkennen - + Custom Commands Eigene Befehle - + Post-exit command: - Nach-abschluss-Befehl: + Nach-Abschluss-Befehl: - + Pre-launch command: Vor-Start-Befehl: - + Pre-launch command runs before the instance launches and post-exit command runs after it exits. Both will be run in MultiMC's working directory with INST_ID, INST_DIR, and INST_NAME as environment variables. - Vor-Start wird ausgeführt, bevor die Instanz startet, Nach-Ende nachdem die Instanz beendet wurde. Beide werden Im ausführungsverzeichnis von MultiMC gestartet. Verfügbare Umgebungsvariablen: INST_ID, INST_DIR, INST_NAME. + Der Vor-Start-Befehl wird ausgeführt, bevor die Instanz startet, der Nach-Ende-Befehl, nachdem die Instanz beendet wurde. Beide werden im Hauptverzeichnis von MultiMC gestartet. Verfügbare Umgebungsvariablen: INST_ID, INST_DIR, INST_NAME. - + + FTB Launcher Directory + FTB-Launcher-Ordner + + + + FTB Directory + FTB-Ordner + + + Instance Directory Instanz-Ordner - + + Icons Directory + Symbolordner + + + Mods Directory Modordner - + LWJGL Directory LWJGL-Ordner - + + JSON Editor + JSON-Editor + + + + Invalid + Ungültig + + + + The file chosen does not seem to be an executable + Die ausgewählte Datei scheint keine Anwendung zu sein + + + Development builds - Entwicklerversionen + Entwicklungsversionen - + Development builds contain experimental features and may be unstable. Are you sure you want to enable them? - Entwicklerversionen enthalten experimentelle Features und können instabil sein. Möchtest du sie dennoch aktivieren? + Entwicklungsversionen enthalten experimentelle Features und können instabil sein. Möchtest du sie dennoch aktivieren? - + + Select a Java version + Wähle eine Java-Version + + + Find Java executable Umm... this translation is a bit meh - Java-Anwendung finden + Java-Anwendung finden + + + + Java test success + Java-Test erfolgreich abgeschlossen + + + + Java test failure + Java-Test fehlgeschlagen + + + + The specified java binary didn't work. You should use the auto-detect feature, or set the path to the java executable. + Das ausgewählte Java-Program hat nicht funktioniert. Du solltest die Auto-Erkennung benutzen oder den Pfad zum Java-Programm angeben. @@ -1399,12 +2439,52 @@ p, li { white-space: pre-wrap; } Aufgabenstatus... + + UpdateDialog + + + MultiMC Update + Neue MultiMC-Version + + + + A new MultiMC update is available! + Eine neue Version von MultiMC ist verfügbar! + + + + Update now + Jetzt herunterladen + + + + Update after MultiMC closes + Herunterladen, wenn MultiMC geschlossen wird + + + + Don't update yet + Noch nicht herunterladen + + + + ValidateTask + + + Validating access token: Sending request... + Validiere Zugriffstoken: Sende Anfrage... + + + + Validating access token: Processing response... + Validiere Zugriffstoken: Bearbeite Antwort... + + VersionSelectDialog - Dialog - Dialog + Dialog Show &snapshots? @@ -1412,17 +2492,65 @@ p, li { white-space: pre-wrap; } Show &Nostalgia? - '&Nostalgia'-Versionen anzeigen? + '&Nostalgie'-Versionen anzeigen? - + + Choose Version + Wähle Version + + + Reloads the version list. Instanzliste aktualisieren. - + &Refresh &Aktualisieren + + YggdrasilTask + + + <b>SSL Handshake failed.</b><br/>There might be a few causes for it:<br/><ul><li>You use Windows XP and need to <a href="http://www.microsoft.com/en-us/download/details.aspx?id=38918">update your root certificates</a></li><li>Some device on your network is interfering with SSL traffic. In that case, you have bigger worries than Minecraft not starting.</li><li>Possibly something else. Check the MultiMC log file for details</li></ul> + <b>SSL-Handshake fehlgeschlagen.</b><br/>Es kann mehrere Erklärungen geben:<br/><ul><li>Du benutzt Windows XP und musst <a href="http://www.microsoft.com/en-us/download/details.aspx?id=38918">dein Stammzertifikat aktualisieren</a></li><li>Ein Gerät in deinem Netzwerk mischt sich in den SSL-Verkehr ein. In diesem Fall hast du größere Probleme, als das, dass Minecraft nicht gestartet werden kann.</li><li>Möglicherweise etwas anderes. Prüfe die MultiMC-Logdatei für Details</li></ul> + + + + An unknown error occurred when processing the response from the authentication server. + Ein unbekannter Fehler ist beim Bearbeiten der Antwort des Authentifizierungs-Servers aufgetreten. + + + + Failed to parse Yggdrasil JSON response: %1 at offset %2. + Fehler beim Bearbeiten der Yggdrasil-JSON-Antwort: %1 bei %2. + + + + An unknown error occurred when trying to communicate with the authentication server: %1 + Ein unbekannter Fehler ist bei der Kommunikation mit den Authentifizierungs-Servern aufgetreten: %1 + + + + An unknown Yggdrasil error occurred. + Ein unbekannter Yggdrasil-Fehler ist aufgetreten. + + + + Sending request to auth servers... + Sende Anfrage an die Authentifizierungs-Server... + + + + Processing response from servers... + Bearbeite Antwort des Authentifizierungs-Servers... + + + + Processing. Please wait... + Bearbeite. Bitte warten... + +